Scope and server-bound arguments
Every call into Wexa happens inside a scope: the organization, department and project you are acting within, together with who you are. Scope is the reason a tool call can be short. You ask for context; you do not also have to say whose context, because Wexa already knows.
Where scope comes from
Scope comes from the credential you called with, not from the call. A credential belongs to one identity inside one organization, department and project, and that trio is fixed when the credential is issued — for the Wexa MCP server, on the consent screen where you pick the project before a token is minted. The same scope then applies however you call: through the Wexa MCP server, the REST API, the TypeScript SDK or the Python SDK.
The four arguments you may never pass
Four argument names describe scope rather than work. These are the server-bound arguments:
project_idprojectIDorganization_idexecuted_by
There are two spellings of the project because two parts of the platform spell it differently, and
both are refused, so neither becomes a way around the other. executed_by is on the list for the
same reason as the rest: who ran something is a fact about the caller, and a caller who could
assert it could sign someone else's name into the audit record.
How the refusal actually works
Both SDKs check the payload's keys before a request is built, and raise a validation error naming the offending arguments. It is a check on the call at the client, not a restriction expressed in the types — the mistake is caught at run time, but it is caught before anything reaches the network.
// ValidationError: ['project_id'] are bound server-side from your
// token scope; sending them is rejected
await fabric.call('query-context', {
project_id: 'proj_123',
query: 'MATCH (c:Customer) RETURN c LIMIT 10',
})Why refusing beats accepting
The refusal is deliberate, and it replaced something worse. Without it, naming one of these four does not fail — the gateway never reads the argument at all. It binds the value from your credential's scope and hands your version straight past. The call succeeds, the answer is about the project your credential is pinned to rather than the one you named, and nothing in the response says so. That is the failure mode that costs the most to find.
Tested directly: a query-context call carrying project_id for a different project returns
200 with an ordinary envelope. It is not compared and not refused. It is ignored.
One clear error, raised at the client, replaced both behaviours. It also makes the property easy to state: if a caller could name the project, then a credential issued for one project could reach another simply by asking, and every isolation guarantee underneath it would be decoration.
What this means when you read an argument table
Tool reference pages mark server-bound arguments explicitly. Read them as documentation of what
Wexa supplies, not as fields you have left blank. The same applies to routes that take a project
in the URL: the platform checks the path against your credential rather than trusting it, and
answers 403 when the two disagree.
Scope is also what makes the platform's records meaningful — see projects for what the project boundary holds, and organizations, departments and projects for the three levels a scope is made of.