Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Capman

FreeNot checked

Exposes capman capability manifests as typed, governed MCP tools for use with Claude Desktop or any MCP-compatible client, with approval, privacy, and risk filt

GitHubEmbed

About

Exposes capman capability manifests as typed, governed MCP tools for use with Claude Desktop or any MCP-compatible client, with approval, privacy, and risk filtering.

README

MCP (Model Context Protocol) adapter for capman — exposes a capman capability manifest as a typed, governed set of MCP tools callable by Claude Desktop, the Claude API, or any MCP-compatible client.

Version: 0.1.0 · Node.js: ≥ 18 · capman peer: ≥ 0.6.3 · License: MIT


Table of Contents

  1. Overview
  2. Architecture
  3. Installation
  4. Quick start — Claude Desktop
  5. Demo mode
  6. Operating modes
  7. Config reference
  8. Capability filtering
  9. Policy gate and risk levels
  10. Registry
  11. Dependency graph
  12. Catalog service
  13. Matching modes
  14. Verdict handling
  15. Audit log
  16. HTTP transport
  17. Troubleshooting

Overview

capman-mcp sits between your capman manifest and any MCP client. It reads your manifest, applies a governance layer (approval, privacy, risk), and exposes each approved capability as a typed MCP tool. Every tool call is translated into engine.ask(), the result is validated, logged, and returned as a structured MCP response.

MCP client (Claude Desktop / API)
         │  tools/list + tools/call (MCP protocol)
         ▼
    capman-mcp
    ├── Approval gate    (allowlist or registry)
    ├── Privacy filter   (public only)
    ├── Risk gate        (policyGate — blocks high-risk by default)
    ├── Dependency graph (cycle detection + impact analysis)
    └── Catalog service  (read-only HTTP discovery API)
         │  engine.ask()
         ▼
       capman  (BM25 → LLM → resolve → HTTP)
         │
         ▼
    Your app's REST API

Architecture

capman-mcp is composed of six independent layers, each in its own module:

Module Responsibility
bridge.ts Converts manifest capabilities to MCP tool definitions; applies all filters
allowlist.ts Loads config; validates allowed capability IDs
server.ts MCP server bootstrap; callTool handler; demo mode
logger.ts Append-only audit log; JSON (production) or human-readable (demo)
registry.ts Persistent capability registry; publish, deprecate, diff
risk.ts Pure risk level derivation from HTTP method, privacy, and error codes
graph.ts Dependency graph; cycle detection; impact analysis
catalog.ts Read-only HTTP catalog service
resolve.ts resolveById — registry-mode bypass of the matcher
schema-derive.ts Input/output schema derivation from capability definitions
output-validate.ts Runtime validation of engine results against declared output schemas

Installation

npm install capman-mcp capman

capman is a peer dependency. Install it alongside capman-mcp so you control the version.


Quick start — Claude Desktop

1. Generate your manifest

# From an existing OpenAPI spec
npx capman generate --from openapi.json

# Or from a capman.config.js you wrote
npx capman generate

This produces capman.manifest.json in your working directory.

2. Create capman-mcp.config.js

// capman-mcp.config.js
module.exports = {
  manifest: '/absolute/path/to/capman.manifest.json',
  baseUrl:  'https://api.your-app.com',
  mode:     'balanced',
  dryRun:   false,
  transport: 'stdio',

  allowedCapabilities: [
    { id: 'get_order' },
    { id: 'list_products' },
    { id: 'check_availability' },
  ],

  audit: {
    enabled: true,
    logFile: '.capman/mcp-audit.log',
  },
}

Always use absolute paths. Claude Desktop resolves paths from its own working directory, not yours. Relative paths will silently fail to load.

3. Add capman-mcp to Claude Desktop

Open your Claude Desktop config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Add a new entry under mcpServers:

{
  "mcpServers": {
    "my-app": {
      "command": "npx",
      "args": [
        "capman-mcp",
        "start",
        "--config",
        "/absolute/path/to/capman-mcp.config.js"
      ]
    }
  }
}

4. Test before connecting

Run the server manually first to confirm the config loads cleanly:

npx capman-mcp start --config /absolute/path/to/capman-mcp.config.js

Expected output:

[capman-mcp] Loaded manifest: your-app (12 capabilities)
[capman-mcp] 8 tools registered
[capman-mcp] MCP server running on stdio

5. Restart Claude Desktop

Quit Claude Desktop completely and reopen it. Your capabilities are now available as tools.


Demo mode

Try capman-mcp with a bundled sample manifest — no real app, no config, no API keys:

npx capman-mcp demo

This starts a dryRun: true server with 4 sample e-commerce capabilities. To connect Claude Desktop, add this to claude_desktop_config.json:

{
  "mcpServers": {
    "capman-demo": {
      "command": "npx",
      "args": ["capman-mcp", "demo"]
    }
  }
}

Then restart Claude Desktop and ask: "get order ORD-123" or "list products".


Operating modes

capman-mcp supports two approval modes. Choose one per deployment.

Config mode (default)

The allowedCapabilities array in your config file is the source of truth for which capabilities are exposed. Straightforward for single-service or single-team setups.

allowedCapabilities: [
  { id: 'get_order' },
  { id: 'list_products', descriptionOverride: 'Browse the product catalog' },
  { id: 'delete_account', allowHighRisk: true },
]

Registry mode

Set registryPath to enable registry-based approval. Approval state, risk level, dependency declarations, and deprecation are all stored in a versioned JSON registry file. Intended for teams where a CI pipeline publishes capabilities and a separate approval step gates MCP exposure.

module.exports = {
  manifest:      '/path/to/capman.manifest.json',
  registryPath:  '/path/to/.capman-mcp/registry.json',
  transport:     'stdio',
  // allowedCapabilities can still be used for descriptionOverride / dryRunOverride
  allowedCapabilities: [],
}

In registry mode, resolveById is used instead of engine.ask() — the tool name directly identifies the capability, bypassing the matcher entirely for lower latency.


Config reference

CapmanMcpConfig

Field Type Required Default Description
manifest string Absolute path to capman.manifest.json
baseUrl string Base URL for API resolvers
mode 'cheap' | 'balanced' | 'accurate' 'balanced' Matching mode (config mode only)
dryRun boolean false Plan API calls without executing them
transport 'stdio' | 'http' 'stdio' MCP transport
httpPort number 3000 Port when transport: 'http'
allowedCapabilities AllowedCapabilityEntry[] ✅* *Required in config mode; optional override layer in registry mode
registryPath string Enables registry mode when set
policyGate boolean true Block high-risk capabilities unless explicitly opted in
auth CapmanMcpAuthConfig Auth context for the server instance. Required to expose user_owned capabilities
audit.enabled boolean true Enable invocation logging
audit.logFile string stderr Append-only audit log path

AllowedCapabilityEntry

Field Type Required Description
id string Capability ID from your manifest
descriptionOverride string Replaces the capability description shown in the MCP tool listing
dryRunOverride boolean Per-capability dry-run — takes precedence over global dryRun
allowHighRisk boolean Explicitly expose this capability despite a high risk level

CapmanMcpAuthConfig

Field Type Required Default Description
isAuthenticated boolean Must be true for user_owned capabilities to be exposed and executed
userId string Injected by capman into params marked source: 'session'. Never exposed to the agent
role 'user' | 'admin' 'user' User's role. admin capabilities remain hard-blocked regardless of this value

Capability filtering

buildToolList applies four filters in order before exposing a capability as an MCP tool. A capability must pass all four to appear.

Filter Condition to pass Notes
1. Approval In allowedCapabilities (config mode) or approvedForMcp: true in registry
2. Privacy privacy.level === 'public' user_owned and admin require auth context MCP cannot provide
3. Lifecycle lifecycle.status !== 'deprecated' Deprecated capabilities are never surfaced
4. Risk gate riskLevel !== 'high' OR allowHighRisk: true OR riskOverride: 'allow' Controlled by policyGate — see below

Exposing user_owned capabilities

By default capman-mcp only exposes public capabilities — those that require no authentication. Many real-world agent workflows need to act on behalf of a specific user: retrieving their orders, updating their account settings, or fetching personalised data. These capabilities have privacy.level === 'user_owned' in the capman manifest.

To expose them, add an auth block to your config:

module.exports = {
  manifest: '/path/to/capman.manifest.json',
  baseUrl:  'https://api.your-app.com',
  transport: 'stdio',

  auth: {
    isAuthenticated: true,
    userId: 'usr-alice-123',  // the user this server instance acts as
    role:   'user',
  },

  allowedCapabilities: [
    { id: 'get_my_orders' },       // user_owned — exposed because auth is set
    { id: 'get_product_catalog' }, // public — always exposed
  ],
}

What auth does

  • The privacy filter in buildToolList allows user_owned capabilities through alongside public ones.
  • capman receives the AuthContext on every tool call and enforces privacy.level at execution time — if isAuthenticated is false, capman rejects the call.
  • capman injects auth.userId into params marked source: 'session' before making the API call. For example, a capability defined with a user_id session param and path /users/{user_id}/orders will automatically call /users/usr-alice-123/orders. The agent never sees or supplies the userId — it is excluded from the MCP input schema entirely.

Privacy levels and auth

privacy.level No auth auth.isAuthenticated: true
public ✅ Exposed ✅ Exposed
user_owned ❌ Blocked ✅ Exposed
admin ❌ Blocked ❌ Blocked always

Limitations

This is a static, server-level identity. Every tool call on this server instance runs as the same user. This is correct for:

  • Personal Claude Desktop setups (one person, one server)
  • Single-user API automations

It is not suitable for multi-user deployments where different callers need different identities. Per-request identity requires transport-level auth signal support, which will be added in a future release when the MCP protocol standardises per-request auth headers.


Policy gate and risk levels

Every capability is assigned a risk level automatically on registry publish and at tool-list build time. The derivation rules are applied top-down, first match wins.

Rule Condition Risk level
1 privacy.level === 'admin' high
2 Any CapabilityError.code contains a financial keyword high
3 Resolver uses POST, PUT, PATCH, or DELETE medium
4 privacy.level === 'user_owned' medium
5 GET/HEAD/OPTIONS + public privacy low

Financial keywords (matched case-insensitively as substrings of the error code): payment, charge, billing, financial, refund, invoice, subscription.

policyGate

When policyGate is true (the default), high-risk capabilities are blocked from MCP exposure unless explicitly opted in.

module.exports = {
  policyGate: true,   // default — safe for production
  allowedCapabilities: [
    { id: 'get_order' },                           // low risk — passes automatically
    { id: 'delete_account', allowHighRisk: true }, // high risk — opted in explicitly
  ],
}

Disable the gate only for fully trusted internal deployments:

policyGate: false

Registry mode risk overrides

In registry mode, each RegistryEntry carries a riskOverride field that takes precedence over the computed riskLevel:

riskOverride value Effect
'allow' Expose despite high risk (operator has reviewed and approved)
'block' Never expose, regardless of risk level (hard block)
absent Default gate behaviour
{
  "fullyQualifiedId": "my-app/create_payment",
  "riskLevel": "high",
  "riskOverride": "allow",
  "approvedForMcp": true
}

Registry

The registry is a persistent JSON file that tracks every published capability with its approval state, risk level, schema hash, and dependency declarations. It is the source of truth in registry mode and the backing store for the catalog service.

CLI commands

# Publish all capabilities from a manifest into the registry
capman-mcp registry publish --manifest capman.manifest.json --owner ci-bot

# Publish without approving for MCP (pending review state)
capman-mcp registry publish --manifest capman.manifest.json --no-approved-for-mcp

# List all registry entries with status, risk, and approval state
capman-mcp registry list

# Show what would change if you published a new manifest version
capman-mcp registry diff --manifest capman.manifest.json

# Deprecate a capability (with optional successor)
capman-mcp registry deprecate my-app/old_endpoint --successor my-app/new_endpoint

# Show all capabilities that depend on a given capability
capman-mcp registry impact my-app/get_order

# All commands accept --registry <path> to target a non-default registry file

registry list output

ID                                    STATUS    RISK     APPROVED  OWNER
my-app/get_order                      stable    low      true      ci-bot
my-app/create_payment                 stable    high     false     ci-bot
my-app/old_search                     deprecated medium  true      ci-bot

registry diff output

  ~ [changed] [low]    my-app/get_order
  + [new]     [medium] my-app/create_refund
  - [removed]          my-app/legacy_checkout
    [unchanged]        my-app/list_products

RegistryEntry fields

Field Type Description
fullyQualifiedId string "{appSlug}/{capabilityId}"
schemaVersion string Manifest schema version at publish time
owner string Team or CI identity that last published
status LifecycleStatus stable, beta, experimental, deprecated
schemaHash string SHA-256 of the capability definition
approvedForMcp boolean Whether this capability is exposed via MCP
riskLevel 'low' | 'medium' | 'high' Auto-derived on publish
riskOverride 'allow' | 'block' Operator override (optional)
dependsOn string[] Explicit dependency declarations (optional)
publishedAt string ISO 8601 timestamp of last publish
deprecatedAt string ISO 8601 timestamp of deprecation (optional)
successor string fullyQualifiedId of the replacement (optional)

Dependency graph

Declaring dependencies

Set dependsOn on a registry entry to declare that one capability relies on another. Values are fullyQualifiedId strings:

{
  "fullyQualifiedId": "my-shop/order_summary",
  "dependsOn": ["my-shop/get_order", "my-shop/get_customer"]
}

Cycle detection

Cycle detection runs automatically on every registry publish. If a publish would introduce a circular dependency chain, it is rejected before the registry file is written — the operation is atomic.

Error: Circular dependency detected: my-shop/a → my-shop/b → my-shop/c → my-shop/a
Fix: remove one of the dependsOn declarations that forms this cycle.

Impact analysis

Find all capabilities that would be affected if a given capability changes:

capman-mcp registry impact my-shop/get_order
Impact analysis for: my-shop/get_order
2 capabilities would be affected if this changes:

  my-shop/order_summary   (stable, medium)
  my-shop/checkout_flow   (stable, low)

This performs a reverse-graph BFS — it finds every capability that directly or transitively depends on the given one, not just its immediate consumers.


Catalog service

The catalog is a read-only HTTP service that makes your capability registry discoverable. Start it alongside your MCP server or as a standalone process:

capman-mcp catalog start --port 4001 --manifest capman.manifest.json
[capman-mcp] Catalog server running at http://localhost:4001
[capman-mcp] Endpoints:
[capman-mcp]   GET /health
[capman-mcp]   GET /capabilities
[capman-mcp]   GET /capabilities/:fqId
[capman-mcp]   GET /capabilities/:fqId/badge
[capman-mcp]   GET /capabilities/:fqId/impact

The catalog reloads the registry on every request — it always reflects the current state without a restart.

Endpoints

Endpoint Response
GET /health { ok: true, count: N }
GET /capabilities RegistryEntry[] — supports filters
GET /capabilities/:fqId Single RegistryEntry or 404
GET /capabilities/:fqId/badge SVG compatibility badge
GET /capabilities/:fqId/impact { fullyQualifiedId, impacted: string[] }

Query filters for GET /capabilities

Parameter Example Effect
q ?q=order Case-insensitive substring match on fullyQualifiedId and owner
risk ?risk=high Filter by low, medium, or high
status ?status=stable Filter by lifecycle status
approvedForMcp ?approvedForMcp=false Filter by approval state

Parameters combine: GET /capabilities?risk=high&approvedForMcp=true

Badge colours

Embed a capability's MCP compatibility badge anywhere SVG is supported:

<img src="http://localhost:4001/capabilities/my-app/get_order/badge" />
Colour Meaning
🟢 Green approvedForMcp: true, risk level low or medium
🟡 Amber approvedForMcp: true, risk level high — review recommended
🔴 Red approvedForMcp: false or riskOverride: 'block'

Matching modes

capman-mcp delegates matching to capman's engine. Three modes trade API cost against matching accuracy. The mode is set per-server in config.

Mode Behaviour Best for
cheap BM25 keyword only — zero LLM calls Registry mode (tool name is explicit)
balanced Keyword first; LLM fallback when confidence < 50% Most production deployments
accurate LLM over top-3 candidates on every call High-ambiguity capability sets

In registry mode, resolveById is used instead of engine.ask(), making the matching mode irrelevant — the tool name is an exact capability ID.


Verdict handling

Each engine.ask() call returns a verdict that capman-mcp surfaces in the MCP response:

Verdict Meaning MCP response
clear High-confidence match, large margin over runner-up Returned as-is
marginal Top two candidates are close in score Prefixed with [verdict: marginal]
uncertain Confidence below threshold Prefixed with [verdict: uncertain]

The client (Claude) sees the verdict annotation and can ask for user confirmation before acting on a marginal result.


Audit log

When audit.enabled is true, every tool invocation is written as one JSON line:

{
  "ts": "2026-06-13T09:00:00.000Z",
  "capabilityId": "get_order",
  "verdict": "clear",
  "resolvedVia": "keyword",
  "durationMs": 42,
  "dryRun": false,
  "params": ["order_id"],
  "error": null
}

Param values are never logged — only param names. The log is append-only and safe to tail in production. In demo mode, the log is written in human-readable format instead.


HTTP transport

For integrations that cannot use stdio:

module.exports = {
  transport: 'http',
  httpPort:  3000,
}
npx capman-mcp start --config capman-mcp.config.js
# [capman-mcp] MCP server listening on http://localhost:3000

Troubleshooting

Claude Desktop shows no tools after restart

  • Ensure all paths in claude_desktop_config.json are absolute.
  • Run the start command manually in a terminal to see errors directly:
    npx capman-mcp start --config /absolute/path/to/capman-mcp.config.js
    
  • Verify the manifest is valid: npx capman validate

Error: config.manifest must be a non-empty string path

The manifest field is missing from your config or is not a string.

allowlist entry "X" not found in manifest

The ID in allowedCapabilities does not exist in your manifest. Run npx capman inspect to list all valid capability IDs.

allowlist entry "X" filtered out (non-public or deprecated)

The capability exists but has privacy.level !== 'public' or is deprecated. It cannot be exposed as an MCP tool.

Tool calls return Missing required parameters: <name>

capman could not extract the parameter from the query string. In balanced or accurate mode, capman will attempt LLM extraction automatically. In cheap mode, the parameter value must appear literally in the query. Add more examples to the capability definition to improve extraction.

Circular dependency detected: ...

A registry publish was rejected because dependsOn declarations form a cycle. Remove one of the declarations named in the error path.

enrichWithOutputSchemas does not support YAML specs yet

Convert your OpenAPI spec to JSON before calling enrichWithOutputSchemas:

npx js-yaml your-spec.yaml > your-spec.json

License

MIT

from github.com/Hobbydefiningdoctory/capman-mcp

Install Capman in Claude Desktop, Claude Code & Cursor

Recommended · one command, every IDE
unyly install capman-mcp

Installs into Claude Desktop, Claude Code, Cursor & VS Code — handles npx, uvx and build-from-source repos for you.

First time? Get the CLI: curl -fsSL https://unyly.org/install | sh

Or configure manually

Run in your terminal:

claude mcp add capman-mcp -- npx -y github:Hobbydefiningdoctory/capman-mcp

FAQ

Is Capman MCP free?

Yes, Capman MCP is free — one-click install via Unyly at no cost.

Does Capman need an API key?

No, Capman runs without API keys or environment variables.

Is Capman hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install Capman in Claude Desktop, Claude Code or Cursor?

Open Capman on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Capman with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All ai MCPs