Skip to content

Commit 8989fe4

Browse files
committed
feat: WASM bindings for cedar-policy-mcp-schema-generator
Add `cedar-policy-mcp-schema-generator-wasm`, a thin wasm-bindgen wrapper around the existing Rust SchemaGenerator. Enables JavaScript and TypeScript environments (Node.js, browsers) to generate Cedar schemas from MCP tool descriptions with identical behavior to the Rust implementation. Motivated by @lianah's recommendation in cedar-policy#63 to use WASM bindings instead of a TypeScript reimplementation. Changes to cedar-policy-mcp-schema-generator: - Add SchemaGenerator::from_cedarschema_str() and from_cedarschema_str_with_config() convenience constructors - Add SchemaGenerator::get_schema_as_str() for human-readable output - Add SchemaParseError variant to SchemaGeneratorError - 6 new unit tests for the above APIs WASM bindings crate: - Single generateSchema() function exposed via wasm-bindgen - All SchemaGeneratorConfig options exposed (camelCase JS naming) - Returns JSON with schema, schemaJson, error, and isOk fields - Zero direct dependency on cedar-policy-core (all parsing delegated to generator crate's from_cedarschema_str) - 3 Rust unit tests - 8 wasm-bindgen-test integration tests (basic generation, multi-tool, config options, error handling, config defaults) Signed-off-by: tommylauren <tfarley@utexas.edu>
1 parent c835f56 commit 8989fe4

8 files changed

Lines changed: 1483 additions & 29 deletions

File tree

rust/Cargo.lock

Lines changed: 177 additions & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[workspace]
22
members = [
33
"cedar-policy-mcp-schema-generator",
4+
"cedar-policy-mcp-schema-generator-wasm",
45
"mcp-tools-sdk",
56
]
67

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[package]
2+
name = "cedar-policy-mcp-schema-generator-wasm"
3+
description = "WASM bindings for cedar-policy-mcp-schema-generator, exposing SchemaGenerator to JavaScript/TypeScript."
4+
version = "0.1.0"
5+
6+
edition.workspace = true
7+
rust-version.workspace = true
8+
license.workspace = true
9+
categories.workspace = true
10+
keywords.workspace = true
11+
homepage.workspace = true
12+
repository.workspace = true
13+
14+
[lib]
15+
crate-type = ["cdylib", "rlib"]
16+
17+
[dependencies]
18+
cedar-policy-mcp-schema-generator = { path = "../cedar-policy-mcp-schema-generator" }
19+
mcp-tools-sdk = { path = "../mcp-tools-sdk" }
20+
wasm-bindgen = "0.2"
21+
serde = { version = "1.0", features = ["derive"] }
22+
serde_json = "1.0"
23+
24+
[dev-dependencies]
25+
wasm-bindgen-test = "0.3"
26+
serde_json = "1.0"
27+
28+
[lints]
29+
workspace = true
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# cedar-policy-mcp-schema-generator-wasm
2+
3+
WASM bindings for [cedar-policy-mcp-schema-generator](../cedar-policy-mcp-schema-generator/), exposing `SchemaGenerator` to JavaScript and TypeScript via `wasm-bindgen`.
4+
5+
This enables Node.js and browser environments to generate Cedar authorization schemas from MCP tool descriptions with the **exact same behavior** as the Rust implementation, including correct handling of:
6+
7+
- JSON `number` as `Long` or `Decimal` (configurable)
8+
- `additionalProperties` as Cedar tagged entities
9+
- Namespaced type deduplication for nested objects
10+
11+
## Usage
12+
13+
```javascript
14+
const { generateSchema } = require('@cedar-policy/mcp-schema-generator-wasm');
15+
16+
const stub = `
17+
namespace MyServer {
18+
@mcp_principal
19+
entity User;
20+
@mcp_resource
21+
entity McpServer;
22+
action "call_tool" appliesTo {
23+
principal: [User],
24+
resource: [McpServer]
25+
};
26+
}
27+
`;
28+
29+
const tools = JSON.stringify([
30+
{
31+
name: 'read_file',
32+
description: 'Read a file from disk',
33+
inputSchema: {
34+
type: 'object',
35+
properties: { path: { type: 'string' } },
36+
required: ['path'],
37+
},
38+
},
39+
]);
40+
41+
const result = JSON.parse(generateSchema(stub, tools));
42+
43+
if (result.isOk) {
44+
console.log(result.schema); // Human-readable .cedarschema
45+
console.log(result.schemaJson); // JSON for Cedar WASM isAuthorized()
46+
} else {
47+
console.error(result.error);
48+
}
49+
```
50+
51+
## API
52+
53+
### `generateSchema(schemaStub, toolsJson, configJson?)`
54+
55+
| Parameter | Type | Description |
56+
|-----------|------|-------------|
57+
| `schemaStub` | `string` | Cedar schema stub with `@mcp_principal` and `@mcp_resource` annotations |
58+
| `toolsJson` | `string` | MCP tool descriptions as JSON (the `tools` array from `tools/list`) |
59+
| `configJson` | `string?` | Optional configuration as JSON |
60+
61+
**Returns:** JSON string with fields:
62+
63+
| Field | Type | Description |
64+
|-------|------|-------------|
65+
| `schema` | `string \| null` | Generated Cedar schema as `.cedarschema` text |
66+
| `schemaJson` | `string \| null` | Generated schema as JSON (for `isAuthorized()`) |
67+
| `error` | `string \| null` | Error message if generation failed |
68+
| `isOk` | `boolean` | Whether generation succeeded |
69+
70+
### Configuration
71+
72+
```json
73+
{
74+
"includeOutputs": false,
75+
"objectsAsRecords": false,
76+
"eraseAnnotations": true,
77+
"flattenNamespaces": false,
78+
"numbersAsDecimal": false
79+
}
80+
```
81+
82+
| Option | Default | Description |
83+
|--------|---------|-------------|
84+
| `includeOutputs` | `false` | Include tool output schemas in actions |
85+
| `objectsAsRecords` | `false` | Use records instead of entities for objects without `additionalProperties` |
86+
| `eraseAnnotations` | `true` | Remove `@mcp_*` annotations from output |
87+
| `flattenNamespaces` | `false` | Flatten all types into a single namespace |
88+
| `numbersAsDecimal` | `false` | Encode JSON `number` as Cedar `Decimal` instead of `Long` |
89+
90+
## Building
91+
92+
```bash
93+
# Install wasm-pack
94+
cargo install wasm-pack
95+
96+
# Build for Node.js
97+
wasm-pack build --target nodejs --scope cedar-policy
98+
99+
# Build for browsers
100+
wasm-pack build --target web --scope cedar-policy
101+
```
102+
103+
## Relationship to the Rust Generator
104+
105+
This crate is a thin `wasm-bindgen` wrapper around the existing `cedar-policy-mcp-schema-generator` Rust crate. All schema generation logic, type mapping, and edge case handling is delegated to the Rust implementation. The WASM bindings add no independent logic.
106+
107+
## License
108+
109+
Apache-2.0

0 commit comments

Comments
 (0)