Skip to content

Commit dc07dfa

Browse files
authored
Merge pull request #232 from PaulJPhilp/codex/pr-4-mcp-tool-surface-contract
PR-4: MCP tool-surface contract fix (P1)
2 parents b35091d + aaa2569 commit dc07dfa

4 files changed

Lines changed: 86 additions & 17 deletions

File tree

packages/mcp-server/README-END-USER.md

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
# Effect Patterns MCP Server — End User Guide
22

3-
Use the **Effect Patterns MCP server** from your IDE (Cursor, Claude Code, Windsurf, or any MCP client) to search 700+ Effect-TS patterns and browse the rule catalog. The MCP server is a **patterns + rule catalog** tool only; it does not analyze, review, or refactor your code.
3+
Use the **Effect Patterns MCP server** from your IDE (Cursor, Claude Code, Windsurf, or any MCP client) to search 700+ Effect-TS patterns, browse curated skills, and inspect the rule catalog. The MCP server is a **patterns + skills + rule catalog** tool only; it does not analyze, review, or refactor your code.
44

55
---
66

77
## What You Get
88

99
- **Pattern search** — Find patterns by keyword, category, or difficulty (beginner / intermediate / advanced).
1010
- **Pattern details** — Full docs and code examples for any pattern by ID.
11+
- **Skills catalog** — Search and retrieve curated Effect-TS skills by query/category.
1112
- **Rule catalog** (read-only) — List all analysis rule metadata (IDs, severity, categories). No code scanning.
1213

1314
Code analysis, review, refactoring, and pattern code generation are **not** available via MCP; they are offered through the [HTTP API](#http-api) and paid CLI only.
@@ -129,7 +130,7 @@ Never commit API keys; use environment variables or your IDE's secret storage.
129130

130131
## MCP Tools (Free Tier)
131132

132-
The MCP server exposes **exactly three tools** in production and staging. No other tools (including code analysis or review) are available via MCP.
133+
The MCP server exposes **exactly five tools** in production and staging. No other tools (including code analysis or review) are available via MCP.
133134

134135
### 1. `search_patterns`
135136

@@ -181,6 +182,38 @@ No parameters.
181182

182183
---
183184

185+
### 4. `list_skills`
186+
187+
Search skills by query and optional category filters.
188+
189+
| Parameter | Type | Required | Description |
190+
|-----------|------|----------|-------------|
191+
| `q` | string | No | Search query for skill title/content. |
192+
| `category` | string | No | Optional skills category filter. |
193+
| `limit` | number | No | Max results to return. |
194+
195+
**Example prompts:**
196+
197+
- "List skills for Effect testing."
198+
- "Find skills for service architecture."
199+
200+
---
201+
202+
### 5. `get_skill`
203+
204+
Get full details for a specific skill by slug, including full guidance content.
205+
206+
| Parameter | Type | Required | Description |
207+
|-----------|------|----------|-------------|
208+
| `slug` | string | Yes | Skill slug identifier. |
209+
210+
**Example prompts:**
211+
212+
- "Get the skill for effect-service."
213+
- "Show skill details for a testing workflow."
214+
215+
---
216+
184217
## HTTP API
185218

186219
When you use the **hosted** server, the MCP server forwards tool calls to the HTTP API for patterns and rules only. You can also call the API directly (e.g. from scripts or CI) with the same API key. **MCP tools do not call paid endpoints** — analysis, review, refactoring, and generation are available only when using the HTTP API or paid CLI directly.
@@ -217,7 +250,7 @@ Full request/response shapes: see [MCP Server API Reference](../../docs/mcp-serv
217250

218251
## Service Tiers
219252

220-
- **MCP (free):** Patterns and rule catalog only `search_patterns`, `get_pattern`, `list_analysis_rules`. Rate limits apply (e.g. 100 requests per 15 minutes per key). MCP cannot call paid endpoints.
253+
- **MCP (free):** Patterns, skills, and rule catalog — `search_patterns`, `get_pattern`, `list_analysis_rules`, `list_skills`, `get_skill`. Rate limits apply (e.g. 100 requests per 15 minutes per key). MCP cannot call paid endpoints.
221254
- **Paid (HTTP API / CLI only):** Code analysis, code review, consistency analysis, apply refactoring, generate pattern code, and higher limits. Use the HTTP API or paid CLI; these capabilities are not available via MCP.
222255

223256
---

packages/mcp-server/src/tools/tool-implementations.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ export type {
3434

3535
import type { CallApiFn, CallToolResult, LogFn, ToolContext } from "@/tools/tool-types.js";
3636

37+
/**
38+
* Official MCP tool surface contract for production/staging.
39+
* Debug/local may add `get_mcp_config`.
40+
*/
41+
export const OFFICIAL_MCP_TOOL_NAMES = [
42+
"search_patterns",
43+
"get_pattern",
44+
"list_analysis_rules",
45+
"list_skills",
46+
"get_skill",
47+
] as const;
48+
3749
/**
3850
* Registers all Effect Patterns tools with the MCP server.
3951
* Shared implementation for both Stdio and HTTP transports.

packages/mcp-server/tests/mcp-protocol/client-stdio.test.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,15 @@ describe("MCP Client Stdio Connection", () => {
2828
expect(client.isReady()).toBe(true);
2929
});
3030

31-
const PRODUCTION_TOOLS = ["get_pattern", "list_analysis_rules", "search_patterns"] as const;
32-
33-
it("should expose exactly 3 tools in default/production env (no get_mcp_config)", async () => {
31+
const PRODUCTION_TOOLS = [
32+
"get_pattern",
33+
"get_skill",
34+
"list_analysis_rules",
35+
"list_skills",
36+
"search_patterns",
37+
] as const;
38+
39+
it("should expose exactly 5 tools in default/production env (no get_mcp_config)", async () => {
3440
client = await createMCPTestClient({
3541
apiKey: "test-api-key",
3642
apiUrl: "http://localhost:3000",
@@ -40,7 +46,7 @@ describe("MCP Client Stdio Connection", () => {
4046

4147
const tools = await client.listTools();
4248

43-
expect(tools).toHaveLength(3);
49+
expect(tools).toHaveLength(5);
4450
expect([...tools].sort()).toEqual([...PRODUCTION_TOOLS].sort());
4551
expect(tools).not.toContain("get_mcp_config");
4652
});
@@ -50,7 +56,13 @@ describe("MCP Client Stdio Connection", () => {
5056

5157
const tools = await client.listTools();
5258

53-
const allowed = ["search_patterns", "get_pattern", "list_analysis_rules"];
59+
const allowed = [
60+
"search_patterns",
61+
"get_pattern",
62+
"list_analysis_rules",
63+
"list_skills",
64+
"get_skill",
65+
];
5466
const forbidden = [
5567
"analyze_code",
5668
"review_code",
@@ -70,8 +82,8 @@ describe("MCP Client Stdio Connection", () => {
7082
for (const name of tools) {
7183
expect(allowedOptional.has(name)).toBe(true);
7284
}
73-
expect(tools.length).toBeGreaterThanOrEqual(3);
74-
expect(tools.length).toBeLessThanOrEqual(4);
85+
expect(tools.length).toBeGreaterThanOrEqual(5);
86+
expect(tools.length).toBeLessThanOrEqual(6);
7587
});
7688

7789
it("should disconnect gracefully", async () => {

packages/mcp-server/tests/mcp-protocol/local.test.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,15 @@ describe("Local MCP Server", () => {
8282
expect(client.isReady()).toBe(true);
8383
});
8484

85-
const PRODUCTION_TOOLS = ["get_pattern", "list_analysis_rules", "search_patterns"] as const;
86-
87-
it("should expose exactly 3 tools when MCP_DEBUG=false and MCP_ENV=production", async () => {
85+
const PRODUCTION_TOOLS = [
86+
"get_pattern",
87+
"get_skill",
88+
"list_analysis_rules",
89+
"list_skills",
90+
"search_patterns",
91+
] as const;
92+
93+
it("should expose exactly 5 tools when MCP_DEBUG=false and MCP_ENV=production", async () => {
8894
if (!isLocalAvailable) return;
8995
const productionClient = await createMCPTestClient({
9096
apiKey: config.apiKey,
@@ -95,7 +101,7 @@ describe("Local MCP Server", () => {
95101

96102
const tools = await productionClient.listTools();
97103

98-
expect(tools).toHaveLength(3);
104+
expect(tools).toHaveLength(5);
99105
expect([...tools].sort()).toEqual([...PRODUCTION_TOOLS].sort());
100106
expect(tools).not.toContain("get_mcp_config");
101107
await productionClient.close();
@@ -105,7 +111,13 @@ describe("Local MCP Server", () => {
105111
if (!isLocalAvailable) return;
106112
const tools = await client.listTools();
107113

108-
const allowed = ["search_patterns", "get_pattern", "list_analysis_rules"];
114+
const allowed = [
115+
"search_patterns",
116+
"get_pattern",
117+
"list_analysis_rules",
118+
"list_skills",
119+
"get_skill",
120+
];
109121
const forbidden = [
110122
"analyze_code",
111123
"review_code",
@@ -125,8 +137,8 @@ describe("Local MCP Server", () => {
125137
for (const name of tools) {
126138
expect(allowedOptional.has(name)).toBe(true);
127139
}
128-
expect(tools.length).toBeGreaterThanOrEqual(3);
129-
expect(tools.length).toBeLessThanOrEqual(4);
140+
expect(tools.length).toBeGreaterThanOrEqual(5);
141+
expect(tools.length).toBeLessThanOrEqual(6);
130142
});
131143
});
132144

0 commit comments

Comments
 (0)