Skip to main content

outfitter-mcp

Deep patterns for @outfitter/mcp including tool registration, Zod schemas, resources, and server configuration. Use when building MCP servers, registering tools, defining resources, or when "MCP server", "MCP tool", "registerTool", or "@outfitter/mcp" are mentioned.

소스 정보

저장소
outfitter-dev/outfitter
최근 소스 활동
2026년 3월 18일 22:30
감지된 SKILL.md 언어
영어
스타
6
포크
1

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
outfitter-mcp
version
0.1.0
description
Deep patterns for @outfitter/mcp including tool registration, Zod schemas, resources, and server configuration. Use when building MCP servers, registering tools, defining resources, or when "MCP server", "MCP tool", "registerTool", or "@outfitter/mcp" are mentioned.
allowed-tools
Read Write Edit Glob Grep
# MCP Server Patterns Deep dive into @outfitter/mcp patterns. ## Creating a Server ```typescript import { createMcpServer } from "@outfitter/mcp"; const server = createMcpServer({ name: "my-server", version: "0.1.0", description: "Server for AI agents", }); // Register tools before start server.registerTool(searchTool); server.registerTool(createTool); // Start server server.start(); ``` ## Tool Definition ### Basic Tool ```typescript import { Result, ValidationError } from "@outfitter/contracts"; import { z } from "zod"; const InputSchema = z.object({ query: z.string().min(1).describe("Search query"), limit: z.number().int().positive().default(10).describe("Max results"), }); export const searchTool = { name: "search", description: "Search for items. Use when user asks to find or search.", inputSchema: InputSchema, handler: async ( input: z.infer<typeof InputSchema> ): Promise<Result<SearchOutput, ValidationError>> => { const results = await performSearch(input.query, input.limit); return Result.ok({ results, total: results.length }); }, }; ``` ### Schema Best Practices ```typescript const InputSchema = z.object({ // Always use .describe() for AI understanding query: z.string().describe("The search term to look for"), // Provide defaults where sensible limit: z.number().default(10).describe("Maximum number of results"), // Use enums for fixed choices sortBy: z .enum(["name", "date", "relevance"]) .default("relevance") .describe("Field to sort results by"), // Mark optional fields explicitly tags: z.array(z.string()).optional().describe("Filter by tags"), }); ``` ### Tool with Context ```typescript export const myTool = { name: "my_tool", description: "Tool description", inputSchema: InputSchema, handler: async (input, ctx) => { ctx.logger.debug("Tool invoked", { input }); const result = await myHandler(input, ctx); if (result.isErr()) { ctx.logger.error("Tool failed", { error: result.error }); } return result; }, }; ``` ## Resources ### Static Resource ```typescript server.registerResource({ uri: "config://settings", name: "Configuration", description: "Current server configuration", mimeType: "application/json", read: async () => { return JSON.stringify(config, null, 2); }, }); ``` ### Dynamic Resource ```typescript server.registerResource({ uri: "data://users/{id}", name: "User Data", description: "User information by ID", mimeType: "application/json", read: async (uri) => { const id = uri.split("/").pop(); const user = await getUser(id); return JSON.stringify(user); }, }); ``` ### Resource List ```typescript server.registerResourceList({ uri: "data://users", name: "Users", description: "List of all users", list: async () => { const users = await getAllUsers(); return users.map((u) => ({ uri: `data://users/${u.id}`, name: u.name, description: u.email, })); }, }); ``` ## Prompts ```typescript server.registerPrompt({ name: "analyze", description: "Analyze data with specific focus", arguments: [ { name: "focus", description: "What to focus on", required: true }, { name: "depth", description: "Analysis depth", required: false }, ], get: async (args) => { return { messages: [ { role: "user", content: { type: "text", text: `Analyze with focus on: ${args.focus}. Depth: ${args.depth || "normal"}`, }, }, ], }; }, }); ``` ## Error Handling ### Returning Errors ```typescript handler: async (input) => { if (!input.query) { return Result.err(ValidationError.create("query", "is required")); } const item = await findItem(input.id); if (!item) { return Result.err(NotFoundError.create("item", input.id)); } return Result.ok(item); }; ``` ### Error Categories in MCP | Category | MCP Behavior | | ---------- | ------------------------------------------- | | validation | Tool returns error with details | | not_found | Tool returns error with resource info | | internal | Tool returns generic error, logs full error | ## Server Configuration ### Claude Desktop Add to `~/Library/Application Support/Claude/claude_desktop_config.json`: ```json { "mcpServers": { "my-server": { "command": "bun", "args": ["run", "/path/to/server.ts"] } } } ``` ### With Environment Variables ```json { "mcpServers": { "my-server": { "command": "bun", "args": ["run", "/path/to/server.ts"], "env": { "API_KEY": "secret", "LOG_LEVEL": "debug" } } } } ``` ## Deferred Tool Loading For tools that are expensive to load: ```typescript server.registerDeferredTool({ name: "heavy_tool", description: "Expensive tool loaded on demand", load: async () => { const { heavyTool } = await import("./heavy-tool.js"); return heavyTool; }, }); ``` ## Testing MCP Servers ```typescript import { createMcpHarness } from "@outfitter/testing"; // Pass the full McpServer instance, not individual tools const harness = createMcpHarness(server); test("tool returns results", async () => { const result = await harness.callTool("my-tool", { query: "test" }); expect(result.isOk()).toBe(true); expect(result.value.results).toHaveLength(3); }); ``` ## Best Practices 1. **Descriptive schemas** — Use `.describe()` on every field 2. **Sensible defaults** — Provide `.default()` where appropriate 3. **Error categories** — Use taxonomy errors for proper handling 4. **Logging** — Log tool invocations for debugging 5. **Deferred loading** — Lazy load expensive tools 6. **Test harnesses** — Use `createMcpHarness` for testing ## Related Skills - `stack:patterns` — Handler contract - `stack:scaffold` — MCP tool template - `stack:debug` — Troubleshooting MCP issues
GitHub에서 보기