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.

Quellinformationen

Repository
outfitter-dev/outfitter
Letzte Quellaktivität
18. März 2026 um 22:30
Erkannte Sprache von SKILL.md
Englisch
Sterne
6
Forks
1

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
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
Auf GitHub ansehen