> Source: https://wexa.ai/docs/get-started/scope-and-server-bound-arguments

# 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_id`
- `projectID`
- `organization_id`
- `executed_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.

**Passing a server-bound argument**

**TypeScript SDK**

```ts
// 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',
})
```

**Python SDK**

```python
# ValidationError: ['project_id'] are bound server-side from your
# token scope; sending them is rejected
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](/docs/concepts/projects) for what the project boundary holds, and
[organizations, departments and projects](/docs/concepts/tenancy) for the three levels a scope is
made of.
