Noodle Seed
Guides

Connectors

Reach real HTTP APIs and run sandboxed logic. Connectors are declared as data with brokered credentials.

A connector is how a Noodle Seed server reaches a backing system: a SaaS API, a first-party service, or your own API. Connectors are declared as data, and their credentials are resolved by the platform's credential broker, never hard-coded.

Build one with the connector builder, then bind it on the server's use map so tools can call it.

HTTP connectors

connector(id).version(v).http({...}) describes a real HTTP API: a baseUrl, an auth block, and an operations map. Requests and responses map with ${...} expressions.

src/server.ts
import { server, tool, connector, secret, z } from '@noodleseed/one';

const weather = connector('weather')
  .version('1.0.0')
  .http({
    baseUrl: 'https://api.example.com',
    allowedOrigins: ['https://api.example.com'],
    auth: { kind: 'apiKey', header: 'X-Api-Key', secret: secret('WEATHER_API_KEY') },
    operations: {
      current: {
        type: 'read',
        method: 'GET',
        path: '/v1/weather',
        query: { city: '${input.city}' },
        input: z.object({ city: z.string() }),
        output: z.object({ temp_c: z.number() }),
        response: { temp_c: '${response.temperature}' },
      },
    },
  });

export default server('weather', { title: 'Weather', version: '1.0.0', use: { weather } }, [
  tool('current_weather', {
    description: 'Get the current temperature for a city.',
    input: z.object({ city: z.string() }),
    output: z.object({ temp_c: z.number() }),
    fulfil: ({ input, connectors }) => connectors.weather.current({ city: input.city }),
  }),
]);

Credentials

Reference secrets and non-secret config by name; the broker resolves them per tenant at call time.

  • secret("NAME") for credentials (API keys, tokens). Set with noodle secrets set.
  • variable("NAME") for non-secret config (a base URL, a tenant id). Set with noodle variables set.

Supported auth kinds today are bearer, apiKey, and clientCredentials (Shipped) — the latter defaults to the RFC-6749 client-credentials grant, with profile: "custom" for non-standard partner token endpoints. Per-user delegated auth kinds are Roadmap (Phase 3).

Hosts are allowlisted

HTTP connectors are SSRF-guarded: set allowedOrigins to the exact hosts the connector may reach. Requests to other hosts are rejected.

Expressions

An operation maps its request and response declaratively with ${...} expressions instead of imperative code. The common scopes:

ExpressionResolves to
${input.x}A field of the operation input.
${response}The raw HTTP response body (use ${response.field} for a field).
${env.NAME}A managed variable (variable("NAME")).
operations: {
  get_order: {
    type: 'read',
    method: 'GET',
    path: '/orders/${input.id}',                 // interpolate input into the path
    input: z.object({ id: z.string() }),
    output: z.object({ total: z.number() }),
    response: { total: '${response.amount}' },    // map response body to output
  },
}

Managed config (secret("NAME") / variable("NAME")) is set with noodle secrets set / noodle variables set and resolved per tenant by the broker at call time. Per-user ${user.*} expressions are Roadmap (Phase 3).

Compute connectors

When a bit of logic is genuinely needed (reshaping a response, deriving a value), a compute connector runs self-contained TypeScript in a sandbox with no ambient authority: no network, filesystem, secrets, or tokens.

const convert = connector('convert')
  .version('1.0.0')
  .compute('c_to_f', {
    type: 'read',
    input: z.object({ temp_c: z.number() }),
    output: z.object({ temp_f: z.number() }),
    run: (input) => ({ temp_f: input.temp_c * 1.8 + 32 }),
  });

The run function must be self-contained: no closures over outer variables, no imports, no fetch. It reaches other operations only through an allowlisted host.callOperation, and you can bound it with limits (timeout, memory, output size). Bind it on use and call it like any connector.

Binding connectors

  • use exposes a connector to your tools, callable as ctx.connectors.<name>.<operation>().
  • provides registers a connector in the catalog for compute steps to reach via host.callOperation, without exposing it directly to tools.

Roadmap

Adopting an existing MCP server as a connector, or generating a connector from an OpenAPI spec, is Roadmap. noodle import openapi today scaffolds starter code, not a managed connector.

On this page