Skip to main content
Glama

Cumulocity Code Mode

codemode

Run async JavaScript functions to discover and call Cumulocity APIs. Search and describe methods first to avoid unfiltered payloads, then execute a single parameterized request.

Instructions

Read first. Every result starts with a marker line: either Executed against tenant: <url> or a no-active-tenant notice. Verify it matches the tenant you intend to act on before reporting the result. The active tenant is global to this CLI session and can be flipped between calls by set-active-tenant. Without an active tenant, discovery (codemode/docs) works against bundled reference snapshots but live API calls fail with a missing-auth error — call status and set-active-tenant to connect.

A method visible in discovery may still return 404 when the service is not actually installed on the current tenant.

Run an async JavaScript function against the Cumulocity API. Discovery, documentation, and typed API calls all happen inside one function — find what you need and call it in the same run.

The expensive mistake is a hasty API call: an unparameterized request returns large payloads that flood your context. search and describe are cheap — spend calls there first.

Do NOT rely on prior knowledge of these APIs and do not assume anything: the available namespaces and their capabilities are tenant-specific and discovered at runtime. What you think you know about an API may be outdated or may be outclassed by a service on this tenant you have never seen. Verify through search, describe, and docs.

Available globals (do NOT declare these as function parameters):

declare const codemode: {
  /** Ranked fuzzy search over API method names, REST paths, and summaries. Returns the top 20 by score. Pass several phrasings at once — results are unioned. */
  search: (query: string | string[]) => Promise<{
    results: Array<{ target: string, namespace: string, method: string, httpMethod?: string, apiPath?: string, summary?: string, score: number }>
    total: number
    truncated: boolean
  }>
  /**
   * No target: overview of the namespaces on THIS tenant and their
   * responsibilities — ALWAYS your first call.
   * "namespace.method": the typed interface for ONE method — signature,
   * input/output types with OpenAPI docs as JSDoc, related doc ids.
   * Array of method targets (max 5): describe a shortlist in one call and
   * COMPARE their input types before picking.
   * "namespace": every method in it, ONE LINE each (name, path, summary) and
   * NO types — for surveying a domain. The overview's method count is the
   * cost; on a large namespace search first.
   */
  describe: (target?: string | string[]) => Promise<
    { target: string, kind: 'overview' | 'namespace' | 'method', content: string }
    | Array<{ target: string, kind: 'overview' | 'namespace' | 'method', content: string }>
  >
}

declare const docs: {
  /** Fuzzy full-text search over prose documentation topics: domain query languages, concepts, API-area guides. Per-method details live in codemode.describe instead. */
  search: (query: string, opts?: { limit?: number, fuzzy?: number, prefix?: boolean, minScore?: number, maxTextLength?: number }) => Promise<Array<{
    id: string, title: string, text: string, truncated: boolean, kind: 'topic' | 'overview', namespace: string, score: number
  }>>
  /**
   * Full untruncated text of a documentation entry. Return it WHOLE — never
   * slice or truncate doc text: the crucial capability (an operator, a
   * function, a constraint) is often documented near the end, and a blind
   * cut loses exactly the part you searched for. Long doc topics are the
   * one output where length is justified.
   */
  read: (id: string) => Promise<{ id: string, title: string, text: string, kind: string, namespace: string }>
}

// API namespaces: `c8y` (Cumulocity core — always present) plus one global
// per microservice available on the current tenant (e.g. `dtm`), plus any
// external MCP server configured for this connection — each with one typed
// method per operation. `codemode.describe()` lists what this connection
// actually has. If a method seems missing, search with different wording; if
// it truly does not exist, say so instead of improvising:
//   await c8y.getManagedObjectCollectionResource({ pageSize: 5 })

Workflow — ALWAYS in this order: describe() → search → describe(shortlist) → call.

  1. codemode.describe() (no target) — ALWAYS start here. It lists the API namespaces on THIS tenant with their responsibilities. A domain service (asset management, data preparation, …) usually has a far better API for its domain — server-side hierarchy queries, bulk operations — than composing the generic core API. Decide which namespaces could own the problem's domain, and search with each of their vocabularies.

  2. codemode.search(["phrasing 1", "phrasing 2"]) — find candidate methods (top 20 by score). Results usually contain several overlapping endpoints (single-item, collection, count, by-external-id, bulk variants) — read all summaries and shortlist every candidate that could satisfy the request in ONE call, don't grab the first hit. If all results come from one namespace, re-check the overview — another namespace may own the domain with a stronger API. If the expected method is missing, re-search with other domain words before concluding it does not exist — check total too.

  3. codemode.describe(["ns.methodA", "ns.methodB"]) (max 5) — ALWAYS describe before calling, and describe the whole shortlist in one call. Compare the input types: prefer the method whose parameters push the work to the server — query/filter parameters (especially ones marked @format c8y:query or documenting a query grammar), hierarchy/recursive selectors, bulk endpoints — over methods that would force per-item calls or client-side filtering. Describing five candidates costs almost nothing; one wrong or unfiltered API call costs more context than all your discovery combined. If search keeps missing the domain's vocabulary, codemode.describe("<ns>") lists every method in that namespace one line each (no types) — the method count from step 1 is what it costs.

  4. docs.search("...") / docs.read(id) — when a parameter references domain syntax you don't know, read the docs before guessing values. Read doc texts to the END — never .slice() them: the operator or function you need is often documented in the later sections, and a blind cut loses exactly the crucial part.

  5. Call the winner: await c8y.someMethod({ ...params, body }) (path/query/header parameters and body share one flat input object). ONE well-parameterized call beats fetching broadly and filtering in your code, and beats chains of per-item calls. If you catch yourself looping over items to call an API for each one, go back to step 1 — a collection, query, or bulk endpoint usually exists.

  6. Return only the data needed to answer — never return raw unfiltered collections.

Discovery and API calls can be combined in a single run. Methods blocked by the connection access policy are omitted from discovery entirely; a blocked live request fails with an explanatory message — that is a connection-level access restriction, not a Cumulocity API failure, and retrying will not help.

Your code must evaluate to an async function. Return the final value you want; on success it is returned in Toon format.

Examples:

async () => {
  const { results } = await codemode.search('alarms by severity')
  const { content } = await codemode.describe(results[0].target)
  return content
}
async () => {
  return await c8y.getAlarmCollectionResource({ pageSize: 10, severity: 'MAJOR' })
}
async () => {
  const hits = await docs.search('inventory query language syntax')
  return hits.length > 0 ? (await docs.read(hits[0].id)).text : 'no docs found'
}

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
codeYesAn async JavaScript function expression. The globals codemode, docs, c8y, and per-service namespaces are available automatically — do not declare them as parameters. Return the final result.
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses critical behaviors not covered by annotations: every result starts with a marker line for tenant verification; active tenant is global to the session; live API calls fail without an active tenant; methods may return 404 if the service isn't installed; discovery is omitted for blocked methods; and blocked requests fail with explanatory messages. It also warns about context flooding from large payloads and instructs the agent to verify tenant before reporting.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but tightly structured: it opens with the most critical warning ('Read first'), then explains the globals with precise JSDoc-style comments, then gives a numbered workflow followed by examples. Every section earns its place—there's no filler. The front-loading of tenant verification and costly-call warnings is excellent.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is exceptionally complete for a tool that executes arbitrary code. It covers tenant semantics, discovery workflow, failure modes, blocking policies, return conventions, and examples. Since there's no output schema, the description explains the return format ('Return the final value you want; on success it is returned in Toon format'). For a highly complex tool, this is near-exhaustive.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds significant meaning beyond the basic schema's `code` parameter. It explains that the code must be an async function expression, that globals are automatically available, and that the final value is returned. It also provides multiple examples. However, the schema itself fully covers the parameter (100% coverage), so the description's additional value is solid but not exhaustive.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool runs an async JavaScript function against the Cumulocity API and provides discovery, documentation, and typed API calls within one function. It names the specific global objects (codemode, docs, c8y) and explains the workflow, distinguishing from sibling tools (status, set-active-tenant) which manage connection state rather than execute code.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides an explicit, mandatory workflow: describe() → search → describe(shortlist) → call. It strongly emphasizes using discovery first to avoid expensive calls, warns against relying on prior knowledge, and gives detailed guidance on when to use docs.search/read and how to prefer server-side filtering. It also explicitly tells the agent to return only needed data and not raw unfiltered collections.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/schplitt/mc8yp'

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