MCP Server Development
The Model Context Protocol (MCP) is the primary extension mechanism in OMP. An MCP server exposes tools, resources, and prompt templates to any connected LLM host over a standard JSON-RPC transport.
Server Structure
my-mcp-server/
package.json # "type": "module", scripts: { start }
src/
index.ts # creates McpServer, registers handlers, starts transport
tools/
search.ts # one file per tool (optional; any structure works)
resources/
config.ts # resource handlers
prompts/
summarise.ts # prompt templates
tests/
server.test.ts
mcp.json # OMP discovery manifest Minimal Server
// src/index.ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
const server = new McpServer({ name: 'my-server', version: '1.0.0' });
server.tool(
'greet',
{ name: z.string().describe('Name to greet') },
async ({ name }) => ({
content: [{ type: 'text', text: `Hello, ${name}!` }],
})
);
const transport = new StdioServerTransport();
await server.connect(transport); Run with node --experimental-vm-modules dist/index.js or point OMP's config to the source directly via bun src/index.ts.
Tool Definitions
Use Zod to define input schemas. OMP surfaces these to the model as JSON Schema automatically.
Return text, image (base64 + mimeType), or resource (URI reference) content items.
Throw McpError with an ErrorCode constant for structured error reporting to the host.
Mark tools readOnlyHint: true or destructiveHint: true so OMP can gate user confirmation prompts.
Resource Handling
Resources expose data the model can read without invoking a tool. Two patterns:
// Static resource — known URI
server.resource(
'config',
'omp://config/current',
async (uri) => ({
contents: [{ uri: uri.href, text: JSON.stringify(await loadConfig()) }],
})
);
// Dynamic resource template — URI with variables
server.resource(
'log-entry',
new ResourceTemplate('omp://logs/{date}', { list: undefined }),
async (uri, { date }) => ({
contents: [{ uri: uri.href, text: await fetchLog(date) }],
})
); Prompt Templates
Prompts are reusable message templates with typed arguments. OMP lists them in the slash-command palette.
server.prompt(
'summarise',
{ text: z.string(), maxWords: z.number().optional().default(100) },
({ text, maxWords }) => ({
messages: [{
role: 'user',
content: { type: 'text', text: `Summarise in ${maxWords} words:\n\n${text}` },
}],
})
); Discovery Manifest
Place mcp.json at the repo root so OMP can auto-register the server:
{
"id": "my-mcp-server",
"name": "My MCP Server",
"version": "1.0.0",
"description": "What this server provides",
"transport": "stdio",
"command": "bun",
"args": ["src/index.ts"],
"capabilities": ["tools", "resources", "prompts"],
"tags": ["productivity", "search"]
} Submit to the OMP MCP Registry to make your server discoverable by all OMP users.
Testing
- Use
InMemoryTransportfrom the SDK to unit-test handlers without a real subprocess. - Pair a client + server over the in-memory transport, call
client.callTool(), assert results. - Test error paths: missing required args, invalid URI schemes, permission-denied scenarios.
- Integration test: spawn the real process with
StdioServerTransport, connect a test client. - OMP's CI runs
mcp-inspectoragainst registered servers on every PR.