Tools
Tools are the unit of capability on a Wire container. MCP and REST are two transports: same tools, different connection mechanisms. This page is the source of truth for what each tool does, its parameters, and its default visibility on each transport.
Tool reference
Section titled “Tool reference”| Tool | Purpose | MCP default | REST default | Cost |
|---|---|---|---|---|
wire_explore | Browse the container: its shape, and the entries in it | ✅ | ✅ | 1 |
wire_search | Fuzzy hybrid retrieval over raw content | ✅ | ✅ | 5 |
wire_navigate | Traverse from an entry: relationships (filterable by type), siblings, source | ✅ | ✅ | 1 |
wire_write | Save an entry to the container | ✅ | ✅ | 0 |
wire_delete | Remove an entry by ID | ✅ | ✅ | 0 |
wire_status | Container status snapshot | ❌ | ✅ | 0 |
wire_files_list | List uploaded files | ❌ | ✅ | 0 |
wire_files_upload | Upload a file | ❌ | ✅ | 0 |
wire_files_delete | Delete a file and its derived entries | ❌ | ✅ | 0 |
wire_claim | Convert an ephemeral container to a permanent one (ephemeral only) | ✅ | ✅ | 0 |
wire_query | Read-only SQL over structured objects (opt-in, off by default) | ❌ | ❌ | 1 |
Every tool is independently toggleable per transport from the container’s Tools page in the dashboard. The defaults above are what new containers ship with; users can flip any tool on or off for either transport. Inactive tools are hidden from tools/list on MCP and return 404 NOT_FOUND on REST.
The five standard tools (wire_explore, wire_search, wire_navigate, wire_write, wire_delete) are on for both transports on every new container. wire_query is the one tool that ships off on both transports, so no agent sees it until someone turns it on. See wire_query for what it does and who can enable it.
The typical agent journey is explore → search → navigate: use wire_explore to discover what’s in the container and fetch specific rows, use wire_search when you have a question and need fuzzy retrieval across raw content to find the right starting point, and use wire_navigate to move around from a content entry you’ve already landed on.
wire_explore
Section titled “wire_explore”Browse the container: what shape it has, and the entries in it. Two modes, list and get.
Use wire_explore to find your footing — what kinds of thing this container holds, and which entries exist. For fuzzy/semantic retrieval over raw content, use wire_search; to move around from an entry you’ve already landed on, use wire_navigate.
| Parameter | Type | Required | Description |
|---|---|---|---|
mode | string | No | list (default) or get |
id | string | get only | Entry id |
tag | string | No | list only: return only entries carrying this tag |
limit | number | No | list only: how many entries to return (default 25, max 100) |
offset | number | No | list only: pagination offset into entries |
list (default): the container’s shape. entries holds the rows you and your agents wrote — paginated by limit/offset, filterable by tag. Beside it, four groups describe everything else the container holds. Each appears only when the container has that kind, so their presence is itself the answer to “does this container have a knowledge graph / structured objects / uploaded files?”
entities[]— the canonical entity rows background analysis built:id,name,entityType, andmentions(how many entries reference this entity).schemas[]— the field profile of each structured object, per source:object,source,mode(declaredwhen the source declared its schema,accretedwhen Wire folded it from writes), andfields[]ofname/type.composites[]— the shell entry for each uploaded file or chunked write:compositeType,fileName,chunkCount,source. Pass a composite’sidtowire_navigateto reach its chunks.entityTypes[]— the entity type names in this container.
These groups describe the container, not a page of it: each is capped at 50 entries, with hasMore naming any group that was cut, and none of them is affected by limit, offset or tag — those page entries. entryCount is the total live rows in the container, all kinds included.
get: one entry by id, with its relationships (the same shape wire_navigate returns in relationships mode). When the entry is a _composite with _compositeType: 'file' — the system-created entry for every uploaded file — the response includes a resource_link pointing at the file’s wire:// URI. Agents resolve it via resources/read to get a signed download URL. See File downloads (Resources).
Example call
Section titled “Example call”curl -X POST \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"mode": "list", "limit": 25}' \ https://YOUR_ORG_SLUG.api.usewire.io/container/YOUR_CONTAINER_ID/tools/explore{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "wire_explore", "arguments": { "mode": "list", "limit": 25 } }}Return shape
Section titled “Return shape”list:
{ "entries": [{ "id": "…", "content": "…", "source": "agent:mcp", "tags": ["meeting"], "properties": {}, "createdAt": 1767225600000 }], "count": 25, "entryCount": 1432, "entities": [{ "id": "…", "name": "Acme Corp", "entityType": "Company", "mentions": 7 }], "schemas": [{ "id": "…", "object": "expenses", "source": "file:expenses.csv", "mode": "accreted", "fields": [{ "name": "amount", "type": "number" }] }], "composites": [{ "id": "…", "compositeType": "file", "fileName": "runbook.md", "chunkCount": 42, "source": "file:runbook.md" }], "entityTypes": ["Company", "Person"], "hasMore": { "entities": true }}countis how many entries this page returned;entryCountis the container total.entities/schemas/composites/entityTypes/hasMoreare omitted entirely when they’d be empty.
get:
entry: the entry, withcontent,source,tags,propertiesandcreatedAt.relationships:from,to, andbyType— seewire_navigate.
wire_search
Section titled “wire_search”Fuzzy hybrid retrieval over raw content in the container (file chunks, agent writes, and other unstructured entries). Always runs a hybrid pipeline: BM25 + vector embedding + HyDE + LLM rerank.
Use this when you have a question and need semantic search to find relevant passages. To see what the container holds, or to fetch one entry by id, use wire_explore.
Flat 5 credits per call.
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Free-text query |
limit | number | No | Max results. Default 10. Clamped to 1–100. |
topK | number | No | Alias for limit, same clamp. If you send both, limit wins. |
limit and topK are the same parameter under two names — topK is the original spelling and
keeps working. Values outside 1–100 are clamped rather than rejected, so limit: 0 returns one
result and limit: 5000 returns at most 100.
Each match includes _meta.wire.navigate affordance hints telling the agent what a wire_navigate call on this match would find. See the return shape below for the full structure.
Example call
Section titled “Example call”curl -X POST \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"query": "pricing concerns"}' \ https://YOUR_ORG_SLUG.api.usewire.io/container/YOUR_CONTAINER_ID/tools/search{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "wire_search", "arguments": { "query": "pricing concerns" } }}Return shape
Section titled “Return shape”Each match carries:
id: the entry uuid. Pass this directly towire_navigateorwire_delete.score: hybrid relevance score (post-rerank).content: the raw chunk or entry text.provenance: typed metadata object holdingsource,sourceFileId,chunkIndex,totalChunks,ingestedAt,tags,fileName,sectionHeader,chunkSummary, and more. Read the fields directly, no parsing needed._meta.wire.navigatecarries affordance hints forwire_navigate:hasSiblings: count of adjacent chunks in the same source file. Zero means this chunk stands alone.relationshipTypes: map of edge type to count, only non-zero entries. Example:{ "elaborates": 3, "corroborates": 1 }. Tells the agent upfront whichwire_navigate mode: "relationships" type: ...calls would find something.
_meta.wire.duplicates: present only when this result represents more than one instance of the same content (identical after whitespace normalization). Wire keeps every instance as a complete entry with its own timestamp, source, and metadata (repetition is signal, not noise), and collapses them to one representative at search time so results stay clean. The number is the total count of instances in the group, including this representative. Applies to any kind of repetition: agent retries, file re-ingests, recurring connector pulls, repeated log lines._meta.wire.firstSeenAt: earliestingestedAtacross the instance group. Useful when a recurring source keeps re-ingesting the same content and you want to know how long it’s been in the container._meta.wire.mostRecentAt: latestingestedAtacross the group. The representative is the most recent instance, so its provenance answers “when did this last happen” directly._meta.wire.instanceId: id of the group’s instance record. Pass it towire_navigate(mode: "relationships") to enumerate every instance in the group, each with its own timestamp and source._meta.wire.versions: up to 5 instances from the group withsourceandingestedAt, ordered newest first. The representative result’s own provenance gives the latest instance; this list lets agents see prior sources if they need to.
Use these hints to decide whether a wire_navigate call is worth making, to calibrate range or limit params, and to reason about whether content is fresh or recurring. A high duplicates count is itself information (how many times an alert fired, how often the same page was pulled) that browsing the group via instanceId turns into a timeline.
wire_navigate
Section titled “wire_navigate”Traverse from an entry you’ve already landed on — typically a wire_search match. Move to adjacent chunks, to the entry’s source document, or along relationship edges. Flat 1 credit per call.
| Parameter | Type | Required | Description |
|---|---|---|---|
entryId | string | Yes | The entry to traverse from (e.g. a wire_search match id) |
mode | string | No | relationships (default), siblings, or source |
range | number | siblings only | Chunks before AND after the anchor (default 3, max 50) |
type | string or string[] | relationships only | Return only these edge types. Omit for all edges. |
relationships (default): follow the edges touching this entry. Both directions are kept apart — from holds edges where this entry is the source (“this entry contradicts X”), to holds edges where it’s the target (“X contradicts this entry”). The direction matters: labels are written from the new entry’s perspective at classification time, so those two are different statements.
The same edges come back a second time under byType, bucketed by label, so “what contradicts this?” is one call whether or not you filtered.
siblings: adjacent chunks from the same source document. Positional navigation — given a chunk, returns range chunks before and range chunks after it.
source: the source (composite) entry this one was chunked from. When that source is an uploaded file, the response also carries a resource_link pointing at the file’s wire:// URI; call resources/read on it to get the original bytes. See File downloads (Resources).
Filtering by edge type
Section titled “Filtering by edge type”type takes one label or a list of them:
| Family | Types |
|---|---|
| Provenance | corroborates, elaborates, supersedes, contradicts |
| Structural | part_of (chunk → its document), instance_of (entry → its duplicate group) |
| Entity graph | mentions (entry → a canonical entity), related_via (entity → entity) |
| CRM mirrors | crm_assoc:{field}, one per lookup field on the mirrored record |
A term ending in : matches a whole family by prefix — type: "crm_assoc:" returns every crm_assoc:{field} edge, which is the only way to ask for them without knowing the source system’s field names. Nothing else is a wildcard: contradicts never matches a longer type.
An unrecognized type simply matches nothing. A type that isn’t a string or an array of strings is an error rather than a silently unfiltered result.
wire_search hits carry _meta.wire.navigate.relationshipTypes — a map of edge type to count for that entry, computed from the same grouping — so an agent can see which filtered call would find something before making it.
Example call
Section titled “Example call”After a wire_search call returns a chunk id, fetch surrounding context:
curl -X POST \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"entryId": "entry_abc123", "mode": "siblings", "range": 3}' \ https://YOUR_ORG_SLUG.api.usewire.io/container/YOUR_CONTAINER_ID/tools/navigate{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "wire_navigate", "arguments": { "entryId": "entry_abc123", "mode": "relationships", "type": "contradicts" } }}Return shape
Section titled “Return shape”relationships:
{ "relationships": { "from": [{ "fromId": "entry_abc123", "toId": "entry_def456", "type": "contradicts", "properties": {} }], "to": [], "byType": { "contradicts": { "from": [{ "fromId": "entry_abc123", "toId": "entry_def456", "type": "contradicts", "properties": {} }], "to": [] } } }, "type": ["contradicts"]}type echoes the filter and is absent when you didn’t send one. byType is always present; it’s {} when the entry has no edges.
siblings returns siblings[], and source returns source — entries in the same shape wire_explore mode: "get" returns.
wire_write
Section titled “wire_write”Save an entry to the container.
| Parameter | Type | Required | Description |
|---|---|---|---|
content | string or object | Yes | The entry content. Strings are stored as text. Objects are stored as structured data. |
tags | string[] | No | Tags for categorization and filtering |
metadata | object | No | Arbitrary key-value metadata |
source | string | No | Where this entry came from. Defaults to "agent:mcp" for MCP calls and "webhook:<api-key-name>" for REST calls. |
occurredAt | string | No | When this entry happened, as an ISO 8601 date. Defaults to the write time and must not be in the future. Use it to backfill historical memory (imported notes, past conversations) so the entry’s ingestedAt provenance reflects when the event happened, not when it was imported. |
object | string | No | Group same-shaped records under an object name, e.g. "expenses". See Objects. |
fields | object | No | The record’s queryable values, e.g. {"amount": 42.5, "vendor": "Acme"}. Only meaningful with object, and optional when content is already a JSON object, in which case its keys are used. |
Writing records
Section titled “Writing records”Naming an object turns a write into a row rather than a note: its values are stored so they can be filtered and aggregated, and the container keeps a field profile for the object describing what it has seen.
{ "content": "Lunch with the Acme team", "object": "expenses", "fields": { "amount": 42.5, "vendor": "Acme", "date": "2026-07-24" }}No setup is needed: the first write creates the object and later writes widen it. Reuse the same object name for every record of a kind; a new name per write is capped and makes the profile useless.
The response echoes what the entry was filed under:
| Field | Meaning |
|---|---|
object | The object’s canonical name. May differ in case from what you passed, because the first spelling an object gets is the one it keeps. |
unknownFields | Present only when writing into an object whose schema comes from a connector, listing keys that schema doesn’t define. The write still lands; this is a heads-up, not an error. |
Object names must start with a letter and contain only letters, digits, and underscores. entries, relationships, and fields are reserved.
Example call
Section titled “Example call”curl -X POST \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"content": "Acme Corp wants to upgrade to Enterprise; needs SSO.", "tags": ["meeting", "acme-corp"]}' \ https://YOUR_ORG_SLUG.api.usewire.io/container/YOUR_CONTAINER_ID/tools/write{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "wire_write", "arguments": { "content": "Acme Corp wants to upgrade to Enterprise; needs SSO.", "tags": ["meeting", "acme-corp"] } }}Return shape
Section titled “Return shape”{ "entryId": "entry_abc123", "workflowId": "wf_abc123", "message": "Entry queued for storage. It will be searchable within a few seconds."}entryId: the new entry’s uuid. Pass towire_deleteorwire_navigatelater.workflowId: id of the background write workflow (chunking, embedding, classification). It’s internal; agents don’t need to act on it.message: human-readable status string.
wire_delete
Section titled “wire_delete”Remove an entry by its ID.
| Parameter | Type | Required | Description |
|---|---|---|---|
entryId | string | Yes | The ID of the entry to delete |
includeDuplicates | boolean | No | Also delete every other instance of the same content (the whole group). Default false: only the specified entry. |
When content exists as multiple instances (see _meta.wire.duplicates on wire_search), each instance is independent: deleting one leaves the others untouched, and the group’s counts update. includeDuplicates: true removes the entire group in one call, and the response adds duplicatesDeleted with the number of additional instances removed.
Example call
Section titled “Example call”curl -X POST \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"entryId": "entry_abc123"}' \ https://YOUR_ORG_SLUG.api.usewire.io/container/YOUR_CONTAINER_ID/tools/delete{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "wire_delete", "arguments": { "entryId": "entry_abc123" } }}Return shape
Section titled “Return shape”{ "entryId": "entry_abc123", "workflowId": "wf_abc123"}entryId: echoes the deleted id.workflowId: id of the background delete workflow that cleans up derived chunks, embeddings, and relationship edges. It’s internal; agents don’t need to act on it.
wire_claim
Section titled “wire_claim”Generate a claim link for an ephemeral container. Takes no parameters. Returns a URL that the user can open in a browser to sign up or log in and claim the container permanently.
Claim links are short-lived. Call wire_claim again to generate a new one if needed.
This tool only appears on ephemeral containers (created via instant onboarding). Once a container is claimed and belongs to a permanent organization, wire_claim is no longer listed.
Example call
Section titled “Example call”curl -X POST \ -H "x-api-key: YOUR_API_KEY" \ https://YOUR_ORG_SLUG.api.usewire.io/container/YOUR_CONTAINER_ID/claim{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "wire_claim", "arguments": {} }}Return shape
Section titled “Return shape”{ "claim_url": "https://app.usewire.io/onboarding/create-account?claimToken=...", "expires_in": 3600}claim_url: open in a browser to sign up or log in and claim the container.expires_in: seconds until the claim link expires. Callwire_claimagain to get a fresh one.
wire_status
Section titled “wire_status”Container status snapshot: initialization state, paused flag, counts (tools, entries, entity types), analysis cadence. Useful for readiness checks before kicking off work.
Default visibility: REST on, MCP off. Invoke over REST as GET /container/:id/status.
Takes no parameters.
Example call
Section titled “Example call”curl -H "x-api-key: YOUR_API_KEY" \ https://YOUR_ORG_SLUG.api.usewire.io/container/YOUR_CONTAINER_ID/statusReturn shape
Section titled “Return shape”{ "containerId": "abc123", "containerName": "My Container", "is_ephemeral": false, "initialized": true, "initializationStatus": "complete", "paused": false, "ready": true, "counts": { "tools": 9, "composites": 28, "entityTypes": 17, "entries": { "total": 7381, "eligible": 7102, "analyzed": 7044, "pending": 58 } }, "analysis": { "inProgress": false, "cadence": "automatic" }}ready:truewhen the container is initialized, complete, and not paused. Use this as the gate before kicking off work.initializationStatus: one ofpending,analyzing,generating_tools,complete.counts.entries.pending: eligible entries awaiting their first analysis pass.0means everything has been analyzed at least once.analysis.cadence:automaticormanualper the container’s setting.
wire_files_list
Section titled “wire_files_list”List files uploaded to this container with their processing status.
Default visibility: REST on, MCP off. Invoke over REST as GET /container/:id/files.
Takes no parameters.
Example call
Section titled “Example call”curl -H "x-api-key: YOUR_API_KEY" \ https://YOUR_ORG_SLUG.api.usewire.io/container/YOUR_CONTAINER_ID/filesReturn shape
Section titled “Return shape”[ { "id": "file_abc123", "name": "document.pdf", "size": 245760, "mimeType": "application/pdf", "uploadedAt": "2026-03-30T12:00:00Z", "processingStatus": "complete", "chunkCount": 42 }]Array of file records. Pass id to wire_files_delete or to the wire:// URI scheme via MCP resources to download the original bytes.
processingStatus is pending while the file is queued, processing during extraction, complete once its entries exist, skipped for a download-only file type, and failed if extraction gave up. chunkCount is null until processing finishes.
Over REST this array arrives as the data field of the standard envelope: {"success": true, "data": [ ... ]}. See the REST API reference.
wire_files_upload
Section titled “wire_files_upload”Upload a file to this container. Wire processes it automatically into entries (chunks, extracted entities, embeddings) after upload.
Default visibility: REST on, MCP off. REST is the path built for real files: invoke as POST /container/:id/files with a multipart body containing a file field, and it carries up to 25 MB per file. An owner can also turn the tool on for MCP, where an agent passes the file’s text or bytes as ordinary tool arguments instead. That path is capped at 1 MB, since tool arguments are not a file transfer channel, so anything larger has to go over REST. Files between 25 MB and 50 MB (the platform storage cap) upload from the dashboard. See Supported File Types for accepted formats.
The request must carry a Content-Length header — the endpoint refuses a body whose size it cannot check up front with 411 LENGTH_REQUIRED. curl -F, fetch with a FormData body, and every mainstream HTTP client set it for you.
Over REST:
| Parameter | Type | Required | Description |
|---|---|---|---|
file | multipart file | Yes | The file to upload. Filename + content type are read from the part headers. |
Over MCP (once enabled):
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | File name including extension. The extension drives how the file is processed. |
content | string | One of | UTF-8 text content |
contentBase64 | string | One of | Base64-encoded bytes, for anything not plain text |
mimeType | string | No | Content type, if you want to state it explicitly |
Pass either content or contentBase64, not both, and keep the decoded size under 1 MB.
Example call
Section titled “Example call”curl -X POST \ -H "x-api-key: YOUR_API_KEY" \ -F "file=@customers.csv" \ https://YOUR_ORG_SLUG.api.usewire.io/container/YOUR_CONTAINER_ID/filesReturn shape
Section titled “Return shape”{ "id": "file_abc123", "name": "customers.csv", "size": 245760, "uploadedAt": "2026-03-30T12:00:00Z", "processingStatus": "pending"}id: the new file’s id. Pass towire_files_deleteor towire://resource URIs.processingStatus:pendingimmediately after upload, orskippedwhen the file type is stored for download only. Background workflows extract entries; checkwire_statusorwire_files_listto watch progress.
Over REST the response is 201 Created and this object arrives as the data field of the standard envelope. The content type Wire records is the one it detects from the file’s own bytes, not the one the multipart part declares.
Called over MCP, the tool returns the new file’s id, its name, and a status of either processing or stored. stored means the file type is download-only and no entries will be created from it.
wire_files_delete
Section titled “wire_files_delete”Delete a file and all entries derived from it.
Default visibility: REST on, MCP off. Invoke over REST as DELETE /container/:id/files/:fileId.
| Parameter | Type | Required | Description |
|---|---|---|---|
fileId | string | Yes | The file ID returned by wire_files_list. |
Example call
Section titled “Example call”curl -X DELETE \ -H "x-api-key: YOUR_API_KEY" \ https://YOUR_ORG_SLUG.api.usewire.io/container/YOUR_CONTAINER_ID/files/file_abc123Return shape
Section titled “Return shape”{ "message": "File deleted", "fileId": "file_abc123", "entriesDeleted": 42}entriesDeleted is how many entries derived from the file were removed with it. Deleting a file that isn’t there returns 404 NOT_FOUND, and a file cannot be deleted while it is still being processed.
wire_query
Section titled “wire_query”Read-only SQL over the container’s structured objects, for the answers retrieval cannot give: sums, averages, counts, grouping, exact filters across many records at once.
The tool reaches objects only. Raw content (file chunks, prose entries), the knowledge graph, and container internals are not queryable here; those stay behind wire_explore, wire_search, and wire_navigate.
Flat 1 credit per call.
| Parameter | Type | Required | Description |
|---|---|---|---|
sql | string | Yes | A single read-only SQL statement (SELECT, or WITH … SELECT) |
What you can query
Section titled “What you can query”Two kinds of table exist, and nothing else is reachable.
fields is the catalog. One row per object, source, and field, so an agent can learn the shape of the container before writing a real query. Start every session here:
SELECT * FROM fields| Column | Meaning |
|---|---|
object | Object name, which is also the table name |
source | Where the records came from (a file, a connector, an agent write) |
name | Field name, which is also the column name |
type | integer, number, boolean, date, text, json, or mixed when values disagree |
present | How many of the profiled records actually carry this field |
seen | How many records were profiled for this object and source |
No rows back means the container has no objects yet, and there is nothing to query. present versus seen is worth reading before filtering: a field that appears in 4 of 12 records will silently drop rows from a WHERE clause.
One table per object. Its columns are that object’s profiled field names, plus two the container always adds:
_entry_id: the underlying entry id, so a row in an aggregate can be traced back withwire_navigate._source: the source the record came from.
They carry the underscore prefix because real source data collides: a CSV routinely has its own id and source columns. The same object name written under two sources becomes one table whose columns are the union of both profiles, with _source telling the rows apart; a column missing from one of the profiles reads NULL for those rows.
- One statement per call. A second statement, or one hidden after a comment, is refused.
- Reads only. The statement must begin with
SELECTorWITH. Anything that writes, changes schema, or reaches outside the container is refused, includingPRAGMAand its table-valued forms. - Only declared tables.
FROMandJOINmay name the catalog, an object table, or a CTE the statement defines itself. Any other name comes back as an error telling the agent to runSELECT * FROM fields. json_eachandjson_treeare the only table-valued functions callable. They expand JSON the statement already has.- Results are capped at 200 rows or roughly 256 KB of serialized rows, whichever comes first. Aggregate in SQL rather than paging raw rows.
A refused or invalid statement returns the reason as an error, including the database’s own message for things like an unknown column, which is usually enough for an agent to correct itself and retry.
Example call
Section titled “Example call”curl -X POST \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"sql": "SELECT vendor, sum(amount) AS total FROM expenses GROUP BY vendor ORDER BY total DESC"}' \ https://YOUR_ORG_SLUG.api.usewire.io/container/YOUR_CONTAINER_ID/tools/query{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "wire_query", "arguments": { "sql": "SELECT vendor, sum(amount) AS total FROM expenses GROUP BY vendor ORDER BY total DESC" } }}Return shape
Section titled “Return shape”{ "columns": ["vendor", "total"], "rows": [["Acme", 412.5], ["Globex", 96]], "rowCount": 2, "truncated": false}columns: column names in result order, taken from the statement’s own projection.rows: one array per row, values positioned to matchcolumns. An absent value isnull.rowCount: number of rows inrows.truncated:truewhen the row cap or the size cap cut the result short. Rewrite the query to aggregate rather than asking for the next page.
Choosing between explore, search, and query
Section titled “Choosing between explore, search, and query”wire_explorefor classified canonical entries: what entity types exist, list them, get one by id, filter on a field, keyword-search within a type.wire_searchwhen the question is in natural language and the answer is somewhere in raw content.wire_querywhen the answer is a number or a breakdown over records: totals, averages, counts, group-by, or a precise predicate applied across everything at once.wire_explore’sfiltermode returns matching rows;wire_querycomputes over them.
Activating and deactivating tools
Section titled “Activating and deactivating tools”Every tool can be toggled independently per transport from the container’s Tools page in the dashboard. Three controls govern visibility:
- Active / Inactive: global kill switch. Inactive tools are hidden everywhere.
- MCP pill: when active, controls whether the tool appears in MCP
tools/listand is callable viatools/call. - REST pill: when active, controls whether the underlying REST endpoint serves requests. A disabled REST tool returns
404 NOT_FOUND.
The defaults in the tool reference table at the top of this page are what new containers ship with. User toggles in the dashboard always win over the defaults and are preserved across container wakes.
Toggling a tool is an admin-level action. It takes an organization owner or admin who also has admin permission on the container itself (the creator has it automatically, otherwise it comes from a grant). Organization members cannot toggle tools. That is also the gate on switching wire_query on. See Roles & Permissions.
Public container visibility
Section titled “Public container visibility”A public container is readable by any signed-in Wire user. Connecting still takes a sign-in, which the MCP client prompts for, and Wire then grants the visitor read-only access.
A public visitor sees the read tools: wire_explore, wire_search, and wire_navigate, plus wire_query and wire_status where the owner has switched them on. Write and claim tools (wire_write, wire_delete, wire_claim) are hidden from them. Members of the owning organization, and anyone holding a grant on the container, see the full set their permission allows.
wire_query is read-only, so it follows the same rule. Leave it off if the container is public and its object data is not meant to be aggregated by anyone who connects.
Next Steps
Section titled “Next Steps”- Core Concepts - Learn about entries and containers
- MCP Overview - How to connect and use tools
- REST API - Transport details for invoking tools over HTTP