Skip to main content
Glama

programmatic-mcp

A meta MCP server that:

  • lists MCP servers available in a preset

  • lazily connects to them when list_servers() is called

  • exposes approved server tools to execute_code() as JavaScript libraries

  • stores console output separately through log tools

Config is read from $XDG_CONFIG_HOME/programmatic-mcp/config.json. If XDG_CONFIG_HOME is not set, it falls back to ~/.config/programmatic-mcp/config.json.

Run

node src/index.js
node src/index.js my-preset

The only optional argument is the preset name. If omitted, default is used.

Config

servers uses the same local or remote format as OpenCode MCP config.

presets decides which servers are visible and which tools from each server are allowed.

Example:

{
  "servers": {
    "math": {
      "type": "local",
      "command": ["node", "/absolute/path/to/math-server.js"]
    },
    "docs": {
      "type": "remote",
      "url": "https://example.com/mcp",
      "headers": {
        "Authorization": "Bearer {env:DOCS_TOKEN}"
      }
    }
  },
  "presets": {
    "default": {
      "servers": {
        "math": {
          "tools": ["add", "multiply"]
        },
        "docs": {
          "tools": ["search", "fetch_page"]
        }
      }
    },
    "math-only": ["math"]
  }
}

Accepted preset forms:

  • "preset": ["server-a", "server-b"]

  • "preset": { "servers": { "server-a": true } }

  • "preset": { "servers": { "server-a": { "tools": ["tool1"] } } }

Tool rules:

  • true, omitted tools, or "*" means all tools from that server

  • tools: ["name"] restricts access to the listed tools

  • false or enabled: false removes that server from the preset

OpenCode-style {env:NAME} and {file:path} substitutions are supported.

Exposed Tools

  • list_servers

  • list_tools

  • execute_code

  • fetch_logs

  • clear_logs

Behavior

  • list_servers() lazily starts every server allowed by the preset and returns which ones started successfully

  • list_tools(server) returns only the tools allowed for that server in the preset

  • execute_code(code) does not manage server lifecycle; it can only use servers that are already started

  • console.log, console.info, console.warn, and console.error inside execute_code() are stored for fetch_logs()

  • fetch_logs() drains the log buffer on read

execute_code

execute_code runs JavaScript as the body of an async function.

Started servers are injected as globals. Each allowed MCP tool becomes a function on that server object.

Example:

return await math.add({ a: 2, b: 5 });

If the MCP tool returns structuredContent, that is what the JavaScript call resolves to. So the example above can return:

{
  "sum": 7
}

If a tool name is not a valid JavaScript identifier, bracket access still works:

return await math["tool-name"]({ value: 1 });

If a server name is not a valid identifier, use globalThis:

return await globalThis["my-server"].search({ query: "test" });
-
security - not tested
A
license - permissive license
-
quality - not tested

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/alesya-h/programmatic-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server