@spacelr/mcp 0.0.8 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -4304,6 +4304,2725 @@ function registerAllPrompts(server) {
4304
4304
  registerFunctionPrompts(server);
4305
4305
  }
4306
4306
 
4307
+ // libs/mcp-server/src/resources/getting-started.ts
4308
+ var DOCS = `# Getting Started with Spacelr
4309
+
4310
+ ## Overview
4311
+
4312
+ Spacelr is a **Backend-as-a-Service (BaaS)** platform that provides everything you need to build and run applications. The Spacelr MCP server gives you tools to manage:
4313
+
4314
+ - **Projects** - Create and manage your application projects
4315
+ - **Database** - Document database with collections, documents, indexes, and security rules
4316
+ - **Storage** - File storage with upload, download, sharing, and quotas
4317
+ - **Serverless Functions** - Deploy and execute functions with a built-in KV store
4318
+ - **Hosting** - Static site hosting with deployments and custom domains
4319
+ - **Email Templates** - Manage and preview email templates
4320
+ - **Cron Jobs** - Schedule and manage recurring jobs
4321
+ - **Webhooks** - Configure webhook event delivery
4322
+ - **Notifications** - Send push notifications to users
4323
+ - **Audit Logs** - View audit logs for your projects
4324
+ - **OAuth Clients** - Manage OAuth client applications
4325
+
4326
+ ## Authentication
4327
+
4328
+ The first step is always to authenticate. Use the \`auth_login\` tool with your email and password:
4329
+
4330
+ 1. Call \`auth_login\` with your credentials. After a successful login, the token is stored automatically for subsequent requests.
4331
+ 2. Use \`auth_me\` to verify your current session and see your user profile.
4332
+
4333
+ ## Project Context
4334
+
4335
+ Most tools require a \`projectId\` to specify which project you are working with.
4336
+
4337
+ - Use \`projects_list\` to see all projects you have access to.
4338
+ - Use \`projects_create\` to create a new project if needed.
4339
+
4340
+ Once you have a \`projectId\`, pass it to module-specific tools to manage resources within that project.
4341
+
4342
+ ## Available Documentation Resources
4343
+
4344
+ For detailed documentation on each module, read the following resources:
4345
+
4346
+ | Resource | URI | Description |
4347
+ |----------|-----|-------------|
4348
+ | Authentication | \`spacelr://docs/auth\` | Login, profile management |
4349
+ | Projects | \`spacelr://docs/projects\` | Project and member management |
4350
+ | OAuth Clients | \`spacelr://docs/clients\` | OAuth client management |
4351
+ | Database | \`spacelr://docs/database\` | Collections, documents, indexes, security rules |
4352
+ | Storage | \`spacelr://docs/storage\` | File upload, download, sharing, quotas |
4353
+ | Functions | \`spacelr://docs/functions\` | Serverless functions, deployments, KV store |
4354
+ | Hosting | \`spacelr://docs/hosting\` | Static site hosting, deployments, custom domains |
4355
+ | Email Templates | \`spacelr://docs/email-templates\` | Email template management |
4356
+ | Cron Jobs | \`spacelr://docs/cron-jobs\` | Scheduled job management |
4357
+ | Webhooks | \`spacelr://docs/webhooks\` | Webhook event delivery |
4358
+ | Notifications | \`spacelr://docs/notifications\` | Push notifications |
4359
+ | Audit Logs | \`spacelr://docs/audit-logs\` | Audit log viewing |
4360
+ | Best Practices | \`spacelr://docs/best-practices\` | Setup guide, credentials, recommended workflows |
4361
+
4362
+ ## Quick Start Workflow
4363
+
4364
+ 1. **Authenticate** - Call \`auth_login\` with your email and password.
4365
+ 2. **Find your project** - Call \`projects_list\` to see available projects.
4366
+ 3. **Use module tools** - Pass the \`projectId\` to any module-specific tool (e.g., \`database_collections_list\`, \`storage_files_list\`, \`functions_list\`).
4367
+ `;
4368
+ function registerGettingStartedResources(server) {
4369
+ server.registerResource(
4370
+ "docs-getting-started",
4371
+ "spacelr://docs/getting-started",
4372
+ {
4373
+ title: "Getting Started - Spacelr Docs",
4374
+ description: "Overview of the Spacelr platform, authentication flow, and available modules",
4375
+ mimeType: "text/markdown",
4376
+ annotations: {
4377
+ audience: ["assistant"],
4378
+ priority: 1
4379
+ }
4380
+ },
4381
+ async (uri) => ({
4382
+ contents: [{
4383
+ uri: uri.href,
4384
+ mimeType: "text/markdown",
4385
+ text: DOCS
4386
+ }]
4387
+ })
4388
+ );
4389
+ }
4390
+
4391
+ // libs/mcp-server/src/resources/auth.ts
4392
+ var DOCS2 = `# Authentication Tools
4393
+
4394
+ ## Overview
4395
+
4396
+ The authentication tools provide login, session inspection, and profile management for the Spacelr platform. After a successful login, the access token is stored automatically by the API client and used for all subsequent requests.
4397
+
4398
+ ## Tools Reference
4399
+
4400
+ ### auth_login
4401
+
4402
+ Authenticate with email and password.
4403
+
4404
+ > **WARNING:** The password will be visible in the conversation context. Token values are redacted in the response.
4405
+
4406
+ | Parameter | Type | Required | Description |
4407
+ |------------|--------|----------|--------------------------|
4408
+ | email | string | Yes | A valid email address |
4409
+ | password | string | Yes | Password (min 1 character) |
4410
+
4411
+ **Returns:** The login response with token values redacted.
4412
+
4413
+ ---
4414
+
4415
+ ### auth_me
4416
+
4417
+ Get the currently authenticated user profile.
4418
+
4419
+ | Parameter | Type | Required | Description |
4420
+ |-----------|------|----------|-------------|
4421
+
4422
+ This tool takes no parameters. It returns the profile of the user associated with the current access token.
4423
+
4424
+ ---
4425
+
4426
+ ### auth_update_profile
4427
+
4428
+ Update the currently authenticated user profile. At least one field must be provided.
4429
+
4430
+ | Parameter | Type | Required | Description |
4431
+ |-------------|--------|----------|------------------------------|
4432
+ | firstName | string | No | Updated first name |
4433
+ | lastName | string | No | Updated last name |
4434
+ | displayName | string | No | Updated display name |
4435
+
4436
+ **Returns:** The updated user profile with token values redacted.
4437
+
4438
+ ## Common Workflows
4439
+
4440
+ ### Login Flow
4441
+
4442
+ 1. Call \`auth_login\` with the user's email and password.
4443
+ 2. On success the access token is stored automatically \u2014 no need to pass it manually.
4444
+ 3. All subsequent tool calls will use the stored token for authentication.
4445
+
4446
+ ### Checking the Current Session
4447
+
4448
+ 1. Call \`auth_me\` to retrieve the profile tied to the stored token.
4449
+ 2. If the call fails with an authentication error the token has expired or was never set \u2014 call \`auth_login\` again.
4450
+
4451
+ ### Updating a Profile
4452
+
4453
+ 1. Ensure you are logged in (call \`auth_me\` to verify).
4454
+ 2. Call \`auth_update_profile\` with one or more fields to change.
4455
+ 3. The response contains the full updated profile.
4456
+
4457
+ ## Tips
4458
+
4459
+ - The access token is stored automatically after a successful \`auth_login\` call; you do not need to manage it yourself.
4460
+ - Token values are redacted in all responses to prevent leaking secrets into the conversation context.
4461
+ - Passwords are **not** redacted \u2014 avoid including real credentials in shared conversations.
4462
+ - If a request returns an authentication error, re-authenticate with \`auth_login\`.
4463
+ `;
4464
+ function registerAuthResources(server) {
4465
+ server.registerResource(
4466
+ "docs-auth",
4467
+ "spacelr://docs/auth",
4468
+ {
4469
+ title: "Authentication - Spacelr Docs",
4470
+ description: "Documentation for authentication tools: login, profile, and session management",
4471
+ mimeType: "text/markdown",
4472
+ annotations: {
4473
+ audience: ["assistant"],
4474
+ priority: 0.9
4475
+ }
4476
+ },
4477
+ async (uri) => ({
4478
+ contents: [{
4479
+ uri: uri.href,
4480
+ mimeType: "text/markdown",
4481
+ text: DOCS2
4482
+ }]
4483
+ })
4484
+ );
4485
+ }
4486
+
4487
+ // libs/mcp-server/src/resources/projects.ts
4488
+ var DOCS3 = `# Project Management - Spacelr Docs
4489
+
4490
+ ## Overview
4491
+
4492
+ Projects are the top-level organizational unit in Spacelr. Every resource (database collections, files, functions, etc.) belongs to a project. Use the project tools to create, configure, and manage projects, their members, and roles.
4493
+
4494
+ ## Tools Reference
4495
+
4496
+ ### projects_list
4497
+
4498
+ List all projects the authenticated user has access to.
4499
+
4500
+ | Parameter | Type | Required | Description |
4501
+ |-----------|----------|----------|-----------------------------------|
4502
+ | role | string | No | Filter projects by the user's role |
4503
+
4504
+ ---
4505
+
4506
+ ### projects_get
4507
+
4508
+ Get a single project by its ID.
4509
+
4510
+ | Parameter | Type | Required | Description |
4511
+ |-----------|--------|----------|--------------------|
4512
+ | projectId | string | Yes | The project's ID |
4513
+
4514
+ ---
4515
+
4516
+ ### projects_get_by_slug
4517
+
4518
+ Get a single project by its slug.
4519
+
4520
+ | Parameter | Type | Required | Description |
4521
+ |-----------|--------|----------|---------------------|
4522
+ | slug | string | Yes | The project's slug |
4523
+
4524
+ ---
4525
+
4526
+ ### projects_create
4527
+
4528
+ Create a new project.
4529
+
4530
+ | Parameter | Type | Required | Description |
4531
+ |------------|--------|----------|------------------------------------|
4532
+ | name | string | Yes | Display name of the project |
4533
+ | slug | string | Yes | URL-friendly identifier (unique) |
4534
+ | description | string | No | Short description of the project |
4535
+ | logoUrl | string | No | URL to the project logo (valid URL) |
4536
+ | websiteUrl | string | No | URL to the project website (valid URL) |
4537
+
4538
+ ---
4539
+
4540
+ ### projects_update
4541
+
4542
+ Update an existing project. At least one optional field must be provided.
4543
+
4544
+ | Parameter | Type | Required | Description |
4545
+ |------------|--------|----------|------------------------------------|
4546
+ | projectId | string | Yes | The project's ID |
4547
+ | name | string | No | New display name |
4548
+ | description| string | No | New description |
4549
+ | logoUrl | string | No | New logo URL (valid URL) |
4550
+ | websiteUrl | string | No | New website URL (valid URL) |
4551
+
4552
+ ---
4553
+
4554
+ ### projects_delete
4555
+
4556
+ Delete a project by its ID. This action is irreversible.
4557
+
4558
+ | Parameter | Type | Required | Description |
4559
+ |-----------|--------|----------|--------------------|
4560
+ | projectId | string | Yes | The project's ID |
4561
+
4562
+ ---
4563
+
4564
+ ### projects_members_list
4565
+
4566
+ List members of a project with optional pagination.
4567
+
4568
+ | Parameter | Type | Required | Description |
4569
+ |-----------|---------|----------|--------------------------------|
4570
+ | projectId | string | Yes | The project's ID |
4571
+ | limit | integer | No | Number of results (1-100) |
4572
+ | offset | integer | No | Number of results to skip (>= 0)|
4573
+
4574
+ ---
4575
+
4576
+ ### projects_members_add
4577
+
4578
+ Add a member to a project by email with a specified role.
4579
+
4580
+ | Parameter | Type | Required | Description |
4581
+ |-------------|----------|----------|---------------------------------------------------------------------|
4582
+ | projectId | string | Yes | The project's ID |
4583
+ | email | string | Yes | Email address of the user to add (must be a valid email) |
4584
+ | role | string | Yes | One of: \`owner\`, \`admin\`, \`developer\`, \`member\`, \`viewer\` |
4585
+ | permissions | string[] | No | Array of permission strings to grant |
4586
+
4587
+ ---
4588
+
4589
+ ### projects_members_update
4590
+
4591
+ Update a project member's role, permissions, or console access. At least one optional field must be provided.
4592
+
4593
+ | Parameter | Type | Required | Description |
4594
+ |--------------------|----------|----------|---------------------------------------------------------------------|
4595
+ | projectId | string | Yes | The project's ID |
4596
+ | memberId | string | Yes | The member's ID |
4597
+ | role | string | No | One of: \`owner\`, \`admin\`, \`developer\`, \`member\`, \`viewer\` |
4598
+ | permissions | string[] | No | Updated array of permission strings |
4599
+ | grantConsoleAccess | boolean | No | Whether to grant admin console access |
4600
+
4601
+ ---
4602
+
4603
+ ### projects_members_remove
4604
+
4605
+ Remove a member from a project.
4606
+
4607
+ | Parameter | Type | Required | Description |
4608
+ |-----------|--------|----------|--------------------|
4609
+ | projectId | string | Yes | The project's ID |
4610
+ | memberId | string | Yes | The member's ID |
4611
+
4612
+ ---
4613
+
4614
+ ### projects_users_create
4615
+
4616
+ Create a new user within a project. **WARNING:** The password will be visible in the conversation context.
4617
+
4618
+ | Parameter | Type | Required | Description |
4619
+ |--------------------|----------|----------|---------------------------------------------------------------------|
4620
+ | projectId | string | Yes | The project's ID |
4621
+ | username | string | Yes | Username for the new user |
4622
+ | email | string | Yes | Email address (must be a valid email) |
4623
+ | password | string | Yes | Password (min 1 character) |
4624
+ | role | string | Yes | One of: \`owner\`, \`admin\`, \`developer\`, \`member\`, \`viewer\` |
4625
+ | firstName | string | No | User's first name |
4626
+ | lastName | string | No | User's last name |
4627
+ | displayName | string | No | User's display name |
4628
+ | permissions | string[] | No | Array of permission strings |
4629
+ | grantConsoleAccess | boolean | No | Whether to grant admin console access |
4630
+
4631
+ ---
4632
+
4633
+ ### projects_role
4634
+
4635
+ Get the current authenticated user's role in a specific project.
4636
+
4637
+ | Parameter | Type | Required | Description |
4638
+ |-----------|--------|----------|--------------------|
4639
+ | projectId | string | Yes | The project's ID |
4640
+
4641
+ ---
4642
+
4643
+ ## Common Workflows
4644
+
4645
+ ### Creating a New Project
4646
+
4647
+ 1. Call \`projects_create\` with a \`name\` and a unique \`slug\`.
4648
+ 2. The response contains the new \`projectId\` - use it for all subsequent operations.
4649
+ 3. Optionally call \`projects_update\` to add a logo or website URL.
4650
+
4651
+ ### Managing Members
4652
+
4653
+ 1. Use \`projects_members_list\` to see who is already in the project.
4654
+ 2. Add a new member with \`projects_members_add\`, specifying their email and role.
4655
+ 3. Change a member's role or permissions with \`projects_members_update\`.
4656
+ 4. Remove a member with \`projects_members_remove\`.
4657
+
4658
+ ### Checking Your Role
4659
+
4660
+ Call \`projects_role\` with the \`projectId\` to see what role you hold. This is useful before attempting operations that require elevated privileges.
4661
+
4662
+ ### Creating Project Users
4663
+
4664
+ Use \`projects_users_create\` to provision a user directly inside a project. This creates the user account and assigns them a role in one step.
4665
+
4666
+ ## Tips
4667
+
4668
+ - **Slug uniqueness** - Project slugs must be unique across the tenant. Choose a descriptive, URL-safe value (e.g., \`my-app\`, \`acme-dashboard\`).
4669
+ - **Role hierarchy** - Roles from most to least privileged: \`owner\` > \`admin\` > \`developer\` > \`member\` > \`viewer\`.
4670
+ - **Lookup by slug** - If you know a project's slug but not its ID, use \`projects_get_by_slug\` to resolve it.
4671
+ - **Pagination** - When listing members of large projects, use \`limit\` and \`offset\` to page through results.
4672
+ - **At least one field** - Both \`projects_update\` and \`projects_members_update\` require at least one optional field to be provided; calling them with no changes will return an error.
4673
+ - **Console access** - The \`grantConsoleAccess\` flag on member and user tools controls whether the user can access the admin console.
4674
+ `;
4675
+ function registerProjectResources(server) {
4676
+ server.registerResource(
4677
+ "docs-projects",
4678
+ "spacelr://docs/projects",
4679
+ {
4680
+ title: "Projects - Spacelr Docs",
4681
+ description: "Documentation for project management tools: create, update, members, and roles",
4682
+ mimeType: "text/markdown",
4683
+ annotations: {
4684
+ audience: ["assistant"],
4685
+ priority: 0.9
4686
+ }
4687
+ },
4688
+ async (uri) => ({
4689
+ contents: [{
4690
+ uri: uri.href,
4691
+ mimeType: "text/markdown",
4692
+ text: DOCS3
4693
+ }]
4694
+ })
4695
+ );
4696
+ }
4697
+
4698
+ // libs/mcp-server/src/resources/clients.ts
4699
+ var DOCS4 = `# OAuth Clients
4700
+
4701
+ ## Overview
4702
+
4703
+ OAuth clients represent applications that authenticate users through the Spacelr OAuth service. Each client belongs to a project and defines how an application can request tokens, which scopes it may use, and where users are redirected after login.
4704
+
4705
+ Clients can be **confidential** (server-side apps that can keep a secret) or **public** (SPAs and mobile apps). Confidential clients receive a client secret on creation that is only shown once; use \`clients_regenerate_secret\` if it is lost.
4706
+
4707
+ Secrets returned by list, get, create, and update operations are automatically redacted. Only \`clients_regenerate_secret\` returns the plaintext secret.
4708
+
4709
+ ---
4710
+
4711
+ ## Tools Reference
4712
+
4713
+ ### clients_list
4714
+
4715
+ List all OAuth clients for a project.
4716
+
4717
+ | Parameter | Type | Required | Description |
4718
+ |-------------|----------|----------|------------------------------------|
4719
+ | projectId | string | Yes | The project to list clients for |
4720
+
4721
+ ---
4722
+
4723
+ ### clients_get
4724
+
4725
+ Get details of a specific OAuth client.
4726
+
4727
+ | Parameter | Type | Required | Description |
4728
+ |-------------|----------|----------|---------------------------|
4729
+ | clientId | string | Yes | The ID of the client |
4730
+
4731
+ ---
4732
+
4733
+ ### clients_create
4734
+
4735
+ Create a new OAuth client for a project.
4736
+
4737
+ | Parameter | Type | Required | Description |
4738
+ |----------------|------------|----------|-----------------------------------------------------|
4739
+ | projectId | string | Yes | The project the client belongs to |
4740
+ | name | string | Yes | Human-readable name for the client |
4741
+ | grantTypes | string[] | Yes | OAuth grant types (e.g. authorization_code, client_credentials) |
4742
+ | redirectUris | string[] | No | Valid redirect URIs (must be valid URLs) |
4743
+ | scopes | string[] | No | Scopes the client is allowed to request |
4744
+ | isConfidential | boolean | No | Whether the client is confidential (has a secret) |
4745
+ | corsOrigins | string[] | No | Allowed CORS origins for browser-based flows |
4746
+ | accessTokenTtl | number | No | Access token time-to-live in seconds |
4747
+
4748
+ ---
4749
+
4750
+ ### clients_update
4751
+
4752
+ Update an existing OAuth client. At least one optional field must be provided.
4753
+
4754
+ | Parameter | Type | Required | Description |
4755
+ |----------------|------------|----------|-----------------------------------------------------|
4756
+ | clientId | string | Yes | The ID of the client to update |
4757
+ | name | string | No | Updated client name |
4758
+ | redirectUris | string[] | No | Updated redirect URIs (must be valid URLs) |
4759
+ | scopes | string[] | No | Updated scopes |
4760
+ | grantTypes | string[] | No | Updated grant types |
4761
+ | isActive | boolean | No | Enable or disable the client |
4762
+ | corsOrigins | string[] | No | Updated CORS origins |
4763
+ | accessTokenTtl | number | No | Updated access token TTL in seconds |
4764
+
4765
+ ---
4766
+
4767
+ ### clients_delete
4768
+
4769
+ Delete an OAuth client.
4770
+
4771
+ | Parameter | Type | Required | Description |
4772
+ |-------------|----------|----------|--------------------------------|
4773
+ | clientId | string | Yes | The ID of the client to delete |
4774
+
4775
+ ---
4776
+
4777
+ ### clients_regenerate_secret
4778
+
4779
+ Regenerate the secret for an OAuth client. The new secret is returned in plaintext and can only be retrieved at this moment.
4780
+
4781
+ | Parameter | Type | Required | Description |
4782
+ |-------------|----------|----------|-------------------------------------------|
4783
+ | clientId | string | Yes | The ID of the client to regenerate for |
4784
+
4785
+ ---
4786
+
4787
+ ## Common Workflows
4788
+
4789
+ ### Creating a client for your application
4790
+
4791
+ 1. Use \`clients_create\` with at least \`projectId\`, \`name\`, and \`grantTypes\`.
4792
+ - For a web app with login flow, use \`grantTypes: ["authorization_code"]\` and provide \`redirectUris\`.
4793
+ - For a backend service, use \`grantTypes: ["client_credentials"]\` and set \`isConfidential: true\`.
4794
+ 2. Store the returned client ID (and secret, if confidential) securely.
4795
+
4796
+ ### Regenerating a lost or compromised secret
4797
+
4798
+ 1. Call \`clients_regenerate_secret\` with the \`clientId\`.
4799
+ 2. Copy the new secret from the response immediately -- it will not be shown again.
4800
+ 3. Update your application configuration with the new secret.
4801
+
4802
+ ### Disabling a client temporarily
4803
+
4804
+ Call \`clients_update\` with \`isActive: false\`. Re-enable later with \`isActive: true\`.
4805
+
4806
+ ---
4807
+
4808
+ ## Tips
4809
+
4810
+ - Secrets are only visible at creation time and when explicitly regenerated. All other responses redact them.
4811
+ - Always set \`redirectUris\` for authorization-code clients to prevent open-redirect attacks.
4812
+ - Use \`corsOrigins\` when the client is a browser-based SPA that calls the token endpoint directly.
4813
+ - Set a reasonable \`accessTokenTtl\` to balance security and user experience.
4814
+ `;
4815
+ function registerClientResources(server) {
4816
+ server.registerResource(
4817
+ "docs-clients",
4818
+ "spacelr://docs/clients",
4819
+ {
4820
+ title: "OAuth Clients - Spacelr Docs",
4821
+ description: "Documentation for OAuth client management tools: create, update, and credential rotation",
4822
+ mimeType: "text/markdown",
4823
+ annotations: {
4824
+ audience: ["assistant"],
4825
+ priority: 0.7
4826
+ }
4827
+ },
4828
+ async (uri) => ({
4829
+ contents: [{
4830
+ uri: uri.href,
4831
+ mimeType: "text/markdown",
4832
+ text: DOCS4
4833
+ }]
4834
+ })
4835
+ );
4836
+ }
4837
+
4838
+ // libs/mcp-server/src/resources/database.ts
4839
+ var DOCS5 = `# Database - Spacelr Documentation
4840
+
4841
+ ## Overview
4842
+
4843
+ The Spacelr Database is a **document database** with per-project data isolation, collection-based organization, flexible querying, and a powerful security rules engine. Each project gets its own dedicated database (\`project_{projectId}\`), and all operations are scoped to that project automatically.
4844
+
4845
+ The database module provides tools for:
4846
+
4847
+ - **Collections** - Create, list, and delete collections
4848
+ - **Documents** - Insert, query, update, and delete documents within collections
4849
+ - **Security Rules** - Define access control and validation rules per collection
4850
+ - **Indexes** - Create and manage indexes for query performance
4851
+ - **Index Rules** - Declarative index definitions that can be synced
4852
+ - **Statistics** - View database usage statistics
4853
+
4854
+ ---
4855
+
4856
+ ## Key Concept: Rules-First Approach
4857
+
4858
+ > **Collections are defined through security rules. You MUST set rules before inserting data.**
4859
+
4860
+ This is the single most important concept in the Spacelr database system. Without rules for a collection, **all operations are denied** by the \`$other\` catch-all rule. The correct workflow is always:
4861
+
4862
+ 1. Get the current rules (\`database_rules_get\`)
4863
+ 2. Add your new collection rules to the existing rules object
4864
+ 3. Set the updated rules (\`database_rules_set\`) - this automatically creates the collection
4865
+ 4. Now you can insert and query documents
4866
+
4867
+ **Do NOT** attempt to insert documents before setting rules - it will fail with a "Rule denied" error.
4868
+
4869
+ The \`$other\` catch-all rule should always be present to deny access to undefined collections:
4870
+
4871
+ \`\`\`json
4872
+ {
4873
+ "$other": {
4874
+ ".read": "false",
4875
+ ".write": "false"
4876
+ }
4877
+ }
4878
+ \`\`\`
4879
+
4880
+ ---
4881
+
4882
+ ## Security Rules Syntax
4883
+
4884
+ Each collection in the rules object supports the following rule types:
4885
+
4886
+ | Rule | Purpose | Evaluated on |
4887
+ |------|---------|-------------|
4888
+ | \`.create\` | Controls document inserts | Insert operations |
4889
+ | \`.read\` | Controls document reads and queries | Read/find operations |
4890
+ | \`.update\` | Controls document updates | Update operations |
4891
+ | \`.delete\` | Controls document deletion | Delete operations |
4892
+ | \`.validate\` | Per-field validation expressions | Write operations |
4893
+ | \`.schema\` | Field type declarations | Write operations |
4894
+
4895
+ ### Available Context Variables
4896
+
4897
+ Rules are JavaScript-like expressions that have access to:
4898
+
4899
+ | Variable | Description |
4900
+ |----------|-------------|
4901
+ | \`auth.uid\` | The authenticated user's ID (undefined if not authenticated) |
4902
+ | \`auth.role\` | The authenticated user's role in the project (e.g., \`'owner'\`, \`'admin'\`) |
4903
+ | \`newData\` | The document data being written (available in create/update/validate rules) |
4904
+
4905
+ ### Rule Examples
4906
+
4907
+ **Public read, authenticated create, admin delete:**
4908
+ \`\`\`json
4909
+ {
4910
+ "posts": {
4911
+ ".create": "!!auth.uid",
4912
+ ".read": "true",
4913
+ ".update": "!!auth.uid",
4914
+ ".delete": "auth.role === 'owner' || auth.role === 'admin'"
4915
+ }
4916
+ }
4917
+ \`\`\`
4918
+
4919
+ **Admin-only access:**
4920
+ \`\`\`json
4921
+ {
4922
+ "settings": {
4923
+ ".create": "auth.role === 'owner' || auth.role === 'admin'",
4924
+ ".read": "auth.role === 'owner' || auth.role === 'admin'",
4925
+ ".update": "auth.role === 'owner' || auth.role === 'admin'",
4926
+ ".delete": "auth.role === 'owner' || auth.role === 'admin'"
4927
+ }
4928
+ }
4929
+ \`\`\`
4930
+
4931
+ **Authenticated users only:**
4932
+ \`\`\`json
4933
+ {
4934
+ "messages": {
4935
+ ".create": "!!auth.uid",
4936
+ ".read": "!!auth.uid",
4937
+ ".update": "!!auth.uid",
4938
+ ".delete": "auth.role === 'owner' || auth.role === 'admin'"
4939
+ }
4940
+ }
4941
+ \`\`\`
4942
+
4943
+ ---
4944
+
4945
+ ## Tools Reference
4946
+
4947
+ ### Collections
4948
+
4949
+ #### \`database_collections_list\`
4950
+ List all collections in a project database.
4951
+
4952
+ | Parameter | Type | Required | Description |
4953
+ |-----------|------|----------|-------------|
4954
+ | \`projectId\` | string | Yes | The project ID |
4955
+
4956
+ #### \`database_collections_create\`
4957
+ Create a new collection in a project database.
4958
+
4959
+ | Parameter | Type | Required | Description |
4960
+ |-----------|------|----------|-------------|
4961
+ | \`projectId\` | string | Yes | The project ID |
4962
+ | \`name\` | string | Yes | Collection name |
4963
+ | \`description\` | string | No | Optional description |
4964
+
4965
+ #### \`database_collections_delete\`
4966
+ Delete a collection from a project database.
4967
+
4968
+ | Parameter | Type | Required | Description |
4969
+ |-----------|------|----------|-------------|
4970
+ | \`projectId\` | string | Yes | The project ID |
4971
+ | \`name\` | string | Yes | Collection name to delete |
4972
+
4973
+ ---
4974
+
4975
+ ### Security Rules
4976
+
4977
+ #### \`database_rules_get\`
4978
+ Get the current security rules for a project database.
4979
+
4980
+ | Parameter | Type | Required | Description |
4981
+ |-----------|------|----------|-------------|
4982
+ | \`projectId\` | string | Yes | The project ID |
4983
+
4984
+ #### \`database_rules_set\`
4985
+ Set security rules for a project database. Setting rules for a collection automatically creates it.
4986
+
4987
+ | Parameter | Type | Required | Description |
4988
+ |-----------|------|----------|-------------|
4989
+ | \`projectId\` | string | Yes | The project ID |
4990
+ | \`rules\` | object | Yes | The complete rules object (Record<string, unknown>) |
4991
+ | \`expectedVersion\` | number | No | Optimistic concurrency version to prevent conflicting updates |
4992
+
4993
+ #### \`database_rules_validate\`
4994
+ Validate security rules without applying them. Use this to check rules syntax before committing.
4995
+
4996
+ | Parameter | Type | Required | Description |
4997
+ |-----------|------|----------|-------------|
4998
+ | \`projectId\` | string | Yes | The project ID |
4999
+ | \`rules\` | object | Yes | The rules object to validate (Record<string, unknown>) |
5000
+
5001
+ ---
5002
+
5003
+ ### Index Rules
5004
+
5005
+ #### \`database_index_rules_get\`
5006
+ Get the declarative index rules for a project database.
5007
+
5008
+ | Parameter | Type | Required | Description |
5009
+ |-----------|------|----------|-------------|
5010
+ | \`projectId\` | string | Yes | The project ID |
5011
+
5012
+ #### \`database_index_rules_sync\`
5013
+ Sync index rules for a project database. This applies declarative index definitions.
5014
+
5015
+ | Parameter | Type | Required | Description |
5016
+ |-----------|------|----------|-------------|
5017
+ | \`projectId\` | string | Yes | The project ID |
5018
+ | \`indexRules\` | object | Yes | The index rules object (Record<string, unknown>) |
5019
+
5020
+ ---
5021
+
5022
+ ### Indexes
5023
+
5024
+ #### \`database_indexes_list\`
5025
+ List all indexes for a collection.
5026
+
5027
+ | Parameter | Type | Required | Description |
5028
+ |-----------|------|----------|-------------|
5029
+ | \`projectId\` | string | Yes | The project ID |
5030
+ | \`collectionName\` | string | Yes | The collection name |
5031
+
5032
+ #### \`database_indexes_create\`
5033
+ Create a new index on a collection.
5034
+
5035
+ | Parameter | Type | Required | Description |
5036
+ |-----------|------|----------|-------------|
5037
+ | \`projectId\` | string | Yes | The project ID |
5038
+ | \`collectionName\` | string | Yes | The collection name |
5039
+ | \`fields\` | object | Yes | Index field definitions. Keys are field names, values are \`1\` (ascending), \`-1\` (descending), or \`"text"\` (text index) |
5040
+ | \`unique\` | boolean | No | Whether the index enforces uniqueness |
5041
+ | \`sparse\` | boolean | No | Whether the index is sparse (skips documents missing the field) |
5042
+ | \`ttlSeconds\` | number | No | Time-to-live in seconds for automatic document expiration |
5043
+
5044
+ #### \`database_indexes_delete\`
5045
+ Delete an index from a collection.
5046
+
5047
+ | Parameter | Type | Required | Description |
5048
+ |-----------|------|----------|-------------|
5049
+ | \`projectId\` | string | Yes | The project ID |
5050
+ | \`collectionName\` | string | Yes | The collection name |
5051
+ | \`indexName\` | string | Yes | The name of the index to delete |
5052
+
5053
+ ---
5054
+
5055
+ ### Documents
5056
+
5057
+ #### \`database_documents_find\`
5058
+ Query documents in a collection with optional filtering, sorting, projection, pagination.
5059
+
5060
+ | Parameter | Type | Required | Description |
5061
+ |-----------|------|----------|-------------|
5062
+ | \`projectId\` | string | Yes | The project ID |
5063
+ | \`collectionName\` | string | Yes | The collection name |
5064
+ | \`filter\` | object | No | MongoDB-style query filter (Record<string, unknown>) |
5065
+ | \`sort\` | object | No | Sort specification. Keys are field names, values are \`1\` (ascending) or \`-1\` (descending) |
5066
+ | \`fields\` | string[] | No | Array of field names to include in the result (projection) |
5067
+ | \`limit\` | number | No | Maximum number of documents to return (1-100) |
5068
+ | \`offset\` | number | No | Number of documents to skip (min 0) |
5069
+
5070
+ #### \`database_documents_insert\`
5071
+ Insert one or more documents into a collection.
5072
+
5073
+ | Parameter | Type | Required | Description |
5074
+ |-----------|------|----------|-------------|
5075
+ | \`projectId\` | string | Yes | The project ID |
5076
+ | \`collectionName\` | string | Yes | The collection name |
5077
+ | \`documents\` | object[] | Yes | Array of documents to insert (1-500 documents) |
5078
+
5079
+ #### \`database_documents_update\`
5080
+ Update a specific document in a collection by its ID.
5081
+
5082
+ | Parameter | Type | Required | Description |
5083
+ |-----------|------|----------|-------------|
5084
+ | \`projectId\` | string | Yes | The project ID |
5085
+ | \`collectionName\` | string | Yes | The collection name |
5086
+ | \`docId\` | string | Yes | The document ID to update |
5087
+ | \`update\` | object | Yes | The update operations to apply (Record<string, unknown>) |
5088
+
5089
+ #### \`database_documents_delete\`
5090
+ Delete a specific document from a collection by its ID.
5091
+
5092
+ | Parameter | Type | Required | Description |
5093
+ |-----------|------|----------|-------------|
5094
+ | \`projectId\` | string | Yes | The project ID |
5095
+ | \`collectionName\` | string | Yes | The collection name |
5096
+ | \`docId\` | string | Yes | The document ID to delete |
5097
+
5098
+ ---
5099
+
5100
+ ### Statistics
5101
+
5102
+ #### \`database_stats\`
5103
+ Get database statistics for a project (storage size, document counts, etc.).
5104
+
5105
+ | Parameter | Type | Required | Description |
5106
+ |-----------|------|----------|-------------|
5107
+ | \`projectId\` | string | Yes | The project ID |
5108
+
5109
+ ---
5110
+
5111
+ ## Common Workflows
5112
+
5113
+ ### Setting Up a New Collection
5114
+
5115
+ \`\`\`
5116
+ 1. database_rules_get -> get current rules
5117
+ 2. database_rules_set -> add new collection rules to existing rules
5118
+ 3. database_indexes_create -> (optional) add indexes for query performance
5119
+ 4. database_documents_insert -> start inserting data
5120
+ \`\`\`
5121
+
5122
+ ### CRUD Operations
5123
+
5124
+ \`\`\`
5125
+ Create: database_documents_insert (batch up to 500 documents)
5126
+ Read: database_documents_find (with filter, sort, fields, limit, offset)
5127
+ Update: database_documents_update (by document ID)
5128
+ Delete: database_documents_delete (by document ID)
5129
+ \`\`\`
5130
+
5131
+ ### Managing Indexes
5132
+
5133
+ \`\`\`
5134
+ 1. database_indexes_list -> see existing indexes
5135
+ 2. database_indexes_create -> add new index (ascending, descending, or text)
5136
+ 3. database_indexes_delete -> remove unused indexes
5137
+ \`\`\`
5138
+
5139
+ Alternatively, use **index rules** for declarative index management:
5140
+
5141
+ \`\`\`
5142
+ 1. database_index_rules_get -> see current index rule definitions
5143
+ 2. database_index_rules_sync -> apply updated index rules (adds/removes as needed)
5144
+ \`\`\`
5145
+
5146
+ ### Validating Rules Before Applying
5147
+
5148
+ \`\`\`
5149
+ 1. database_rules_validate -> check syntax without applying
5150
+ 2. database_rules_set -> apply once validation passes
5151
+ \`\`\`
5152
+
5153
+ Use the \`expectedVersion\` parameter on \`database_rules_set\` for optimistic concurrency control when multiple users might be editing rules simultaneously.
5154
+
5155
+ ---
5156
+
5157
+ ## Data Isolation
5158
+
5159
+ Each project has its own isolated database (\`project_{projectId}\`). This means:
5160
+
5161
+ - Collections are scoped to the project automatically
5162
+ - No cross-project data access is possible
5163
+ - Deleting a project's database does not affect other projects
5164
+ - Security rules are defined per project
5165
+
5166
+ Always pass the correct \`projectId\` to every database tool call.
5167
+
5168
+ ---
5169
+
5170
+ ## Tips and Gotchas
5171
+
5172
+ 1. **Always set rules first.** The most common mistake is trying to insert documents into a collection that has no rules defined. Without rules, the \`$other\` catch-all denies all access.
5173
+
5174
+ 2. **Rules replace, not merge.** When calling \`database_rules_set\`, you must pass the **complete** rules object including all collections. Always \`database_rules_get\` first, modify the result, then \`database_rules_set\` with the full object.
5175
+
5176
+ 3. **The \`$other\` catch-all is essential.** Always include \`"$other": { ".read": "false", ".write": "false" }\` in your rules to deny access to undefined collections.
5177
+
5178
+ 4. **Document find has a max limit of 100.** Use \`offset\` for pagination when you need more results.
5179
+
5180
+ 5. **Batch inserts max out at 500 documents.** Split larger datasets into multiple \`database_documents_insert\` calls.
5181
+
5182
+ 6. **Use \`database_rules_validate\` before \`database_rules_set\`.** This catches syntax errors without affecting your live rules.
5183
+
5184
+ 7. **Index creation fields accept three values:** \`1\` (ascending), \`-1\` (descending), or \`"text"\` (full-text search).
5185
+
5186
+ 8. **TTL indexes** auto-delete documents after the specified \`ttlSeconds\`. Useful for session data, logs, or temporary records.
5187
+
5188
+ 9. **Sparse indexes** skip documents that do not contain the indexed field. Useful for optional fields where you only want to index documents that have the field.
5189
+
5190
+ 10. **Use \`expectedVersion\` for safe rule updates.** This prevents accidentally overwriting rule changes made by another user or process.
5191
+
5192
+ 11. **Serverless functions** can access the database using \`spacelr.db.collection("collectionName")\` - the same security rules apply.
5193
+ `;
5194
+ function registerDatabaseResources(server) {
5195
+ server.registerResource(
5196
+ "docs-database",
5197
+ "spacelr://docs/database",
5198
+ {
5199
+ title: "Database - Spacelr Docs",
5200
+ description: "Documentation for database tools: collections, documents, indexes, and security rules",
5201
+ mimeType: "text/markdown",
5202
+ annotations: {
5203
+ audience: ["assistant"],
5204
+ priority: 0.8
5205
+ }
5206
+ },
5207
+ async (uri) => ({
5208
+ contents: [{
5209
+ uri: uri.href,
5210
+ mimeType: "text/markdown",
5211
+ text: DOCS5
5212
+ }]
5213
+ })
5214
+ );
5215
+ }
5216
+
5217
+ // libs/mcp-server/src/resources/hosting.ts
5218
+ var DOCS6 = `# Hosting Tools
5219
+
5220
+ ## Overview
5221
+
5222
+ The hosting tools provide static site hosting capabilities for Spacelr projects. You can create deployments, upload site files, manage custom domains, and configure hosting behaviour such as SPA mode and custom headers.
5223
+
5224
+ ## Tools Reference
5225
+
5226
+ ### Deployments
5227
+
5228
+ #### hosting_deployments_list
5229
+
5230
+ List deployments for a hosting project.
5231
+
5232
+ | Parameter | Type | Required | Description |
5233
+ |------------|--------|----------|-----------------------------------|
5234
+ | projectId | string | Yes | Project ID |
5235
+ | limit | number | No | Max results (1-100) |
5236
+ | offset | number | No | Pagination offset (min 0) |
5237
+
5238
+ ---
5239
+
5240
+ #### hosting_deployments_get
5241
+
5242
+ Get details of a specific deployment.
5243
+
5244
+ | Parameter | Type | Required | Description |
5245
+ |--------------|--------|----------|---------------|
5246
+ | projectId | string | Yes | Project ID |
5247
+ | deploymentId | string | Yes | Deployment ID |
5248
+
5249
+ ---
5250
+
5251
+ #### hosting_deployments_create
5252
+
5253
+ Create a new deployment for a hosting project.
5254
+
5255
+ | Parameter | Type | Required | Description |
5256
+ |-------------|--------|----------|------------------------------------------|
5257
+ | projectId | string | Yes | Project ID |
5258
+ | description | string | No | Human-readable deployment description |
5259
+ | framework | string | No | Framework identifier (e.g. "react") |
5260
+
5261
+ **Returns:** The newly created deployment object including its \`deploymentId\`.
5262
+
5263
+ ---
5264
+
5265
+ #### hosting_deployments_upload
5266
+
5267
+ Upload files to an existing hosting deployment. Accepts a record of filename to content, bundles them into a ZIP archive, and uploads it.
5268
+
5269
+ | Parameter | Type | Required | Description |
5270
+ |--------------|-------------------------|----------|-----------------------------------------------------------------------------|
5271
+ | projectId | string | Yes | Project ID |
5272
+ | deploymentId | string | Yes | Deployment ID (from \`hosting_deployments_create\`) |
5273
+ | files | Record<string, string> | Yes | Map of file path to file content (e.g. \`{ "index.html": "<!DOCTYPE html>..." }\`) |
5274
+
5275
+ Keys are file paths inside the archive (e.g. \`"index.html"\`, \`"assets/style.css"\`). Values are the UTF-8 file contents. At least one file entry is required.
5276
+
5277
+ **Returns:** Upload summary including the list of uploaded filenames and bundle size in bytes.
5278
+
5279
+ ---
5280
+
5281
+ #### hosting_deployments_activate
5282
+
5283
+ Activate a specific deployment, making it the live version.
5284
+
5285
+ | Parameter | Type | Required | Description |
5286
+ |--------------|--------|----------|---------------|
5287
+ | projectId | string | Yes | Project ID |
5288
+ | deploymentId | string | Yes | Deployment ID |
5289
+
5290
+ ---
5291
+
5292
+ #### hosting_deployments_status
5293
+
5294
+ Get the status of a specific deployment.
5295
+
5296
+ | Parameter | Type | Required | Description |
5297
+ |--------------|--------|----------|---------------|
5298
+ | projectId | string | Yes | Project ID |
5299
+ | deploymentId | string | Yes | Deployment ID |
5300
+
5301
+ ---
5302
+
5303
+ #### hosting_deployments_delete
5304
+
5305
+ Delete a specific deployment.
5306
+
5307
+ | Parameter | Type | Required | Description |
5308
+ |--------------|--------|----------|---------------|
5309
+ | projectId | string | Yes | Project ID |
5310
+ | deploymentId | string | Yes | Deployment ID |
5311
+
5312
+ ---
5313
+
5314
+ ### Configuration
5315
+
5316
+ #### hosting_config_get
5317
+
5318
+ Get hosting configuration for a project.
5319
+
5320
+ | Parameter | Type | Required | Description |
5321
+ |-----------|--------|----------|-------------|
5322
+ | projectId | string | Yes | Project ID |
5323
+
5324
+ ---
5325
+
5326
+ #### hosting_config_update
5327
+
5328
+ Update hosting configuration for a project. At least one config field must be provided.
5329
+
5330
+ | Parameter | Type | Required | Description |
5331
+ |-------------|------------------------|----------|------------------------------------------------------|
5332
+ | projectId | string | Yes | Project ID |
5333
+ | spaMode | boolean | No | Enable single-page application mode |
5334
+ | defaultFile | string | No | Default file to serve (e.g. \`"index.html"\`) |
5335
+ | headers | Record<string, string> | No | Custom response headers (key-value pairs) |
5336
+ | enabled | boolean | No | Enable or disable hosting for the project |
5337
+
5338
+ ---
5339
+
5340
+ ### Domains
5341
+
5342
+ #### hosting_domains_list
5343
+
5344
+ List custom domains for a hosting project.
5345
+
5346
+ | Parameter | Type | Required | Description |
5347
+ |-----------|--------|----------|-------------|
5348
+ | projectId | string | Yes | Project ID |
5349
+
5350
+ ---
5351
+
5352
+ #### hosting_domains_get
5353
+
5354
+ Get details of a specific custom domain.
5355
+
5356
+ | Parameter | Type | Required | Description |
5357
+ |-----------|--------|----------|----------------------|
5358
+ | projectId | string | Yes | Project ID |
5359
+ | domain | string | Yes | Domain name |
5360
+
5361
+ ---
5362
+
5363
+ #### hosting_domains_add
5364
+
5365
+ Add a custom domain to a hosting project.
5366
+
5367
+ | Parameter | Type | Required | Description |
5368
+ |--------------------|--------|----------|--------------------------------------------------|
5369
+ | projectId | string | Yes | Project ID |
5370
+ | domain | string | Yes | Domain name to add |
5371
+ | projectSlug | string | Yes | Project slug |
5372
+ | verificationMethod | string | No | Verification method: \`"cname"\` or \`"txt"\` |
5373
+
5374
+ ---
5375
+
5376
+ #### hosting_domains_verify
5377
+
5378
+ Verify a custom domain for a hosting project.
5379
+
5380
+ | Parameter | Type | Required | Description |
5381
+ |-----------|--------|----------|----------------------|
5382
+ | projectId | string | Yes | Project ID |
5383
+ | domain | string | Yes | Domain name to verify |
5384
+
5385
+ ---
5386
+
5387
+ #### hosting_domains_remove
5388
+
5389
+ Remove a custom domain from a hosting project.
5390
+
5391
+ | Parameter | Type | Required | Description |
5392
+ |-----------|--------|----------|----------------------|
5393
+ | projectId | string | Yes | Project ID |
5394
+ | domain | string | Yes | Domain name to remove |
5395
+
5396
+ ---
5397
+
5398
+ #### hosting_domains_set_primary
5399
+
5400
+ Set a custom domain as the primary domain for a hosting project.
5401
+
5402
+ | Parameter | Type | Required | Description |
5403
+ |-----------|--------|----------|--------------------------------|
5404
+ | projectId | string | Yes | Project ID |
5405
+ | domain | string | Yes | Domain name to set as primary |
5406
+
5407
+ ## Common Workflows
5408
+
5409
+ ### Deploying a Static Site
5410
+
5411
+ 1. Call \`hosting_deployments_create\` with the \`projectId\` (and optionally \`description\` and \`framework\`) to create a new deployment.
5412
+ 2. Call \`hosting_deployments_upload\` with the returned \`deploymentId\`, \`projectId\`, and a \`files\` map containing your site files.
5413
+ 3. Call \`hosting_deployments_activate\` with the \`projectId\` and \`deploymentId\` to make the deployment live.
5414
+
5415
+ ### Managing Custom Domains
5416
+
5417
+ 1. Call \`hosting_domains_add\` with the \`projectId\`, \`domain\`, and \`projectSlug\` to register a custom domain.
5418
+ 2. Configure the DNS records as instructed in the response.
5419
+ 3. Call \`hosting_domains_verify\` to confirm DNS propagation and complete verification.
5420
+ 4. Optionally call \`hosting_domains_set_primary\` to make it the primary domain.
5421
+
5422
+ ### Configuring Hosting Behaviour
5423
+
5424
+ 1. Call \`hosting_config_get\` to inspect the current configuration.
5425
+ 2. Call \`hosting_config_update\` with the fields you want to change (e.g. enable \`spaMode\` for a single-page application, set custom \`headers\`, or change the \`defaultFile\`).
5426
+
5427
+ ### Reviewing Deployment Status
5428
+
5429
+ 1. Call \`hosting_deployments_list\` to see all deployments for a project.
5430
+ 2. Call \`hosting_deployments_status\` or \`hosting_deployments_get\` for detailed information on a specific deployment.
5431
+
5432
+ ## Tips
5433
+
5434
+ - Always create a deployment before uploading files \u2014 the \`deploymentId\` is required for the upload step.
5435
+ - A deployment is not live until you explicitly call \`hosting_deployments_activate\`.
5436
+ - The \`files\` parameter in \`hosting_deployments_upload\` accepts nested paths as keys (e.g. \`"assets/style.css"\`) \u2014 no need to flatten your file structure.
5437
+ - Enable \`spaMode\` in the hosting config when deploying single-page applications so that all routes fall back to the default file.
5438
+ - Use \`hosting_deployments_list\` with \`limit\` and \`offset\` to paginate through large numbers of deployments.
5439
+ - Domain verification may take time for DNS propagation \u2014 if \`hosting_domains_verify\` fails, wait and retry.
5440
+ `;
5441
+ function registerHostingResources(server) {
5442
+ server.registerResource(
5443
+ "docs-hosting",
5444
+ "spacelr://docs/hosting",
5445
+ {
5446
+ title: "Hosting - Spacelr Docs",
5447
+ description: "Documentation for static site hosting tools: deployments, domains, and configuration",
5448
+ mimeType: "text/markdown",
5449
+ annotations: {
5450
+ audience: ["assistant"],
5451
+ priority: 0.7
5452
+ }
5453
+ },
5454
+ async (uri) => ({
5455
+ contents: [{
5456
+ uri: uri.href,
5457
+ mimeType: "text/markdown",
5458
+ text: DOCS6
5459
+ }]
5460
+ })
5461
+ );
5462
+ }
5463
+
5464
+ // libs/mcp-server/src/resources/storage.ts
5465
+ var DOCS7 = `# Storage
5466
+
5467
+ ## Overview
5468
+
5469
+ The Storage module provides file storage management capabilities for Spacelr projects. Users can list files, retrieve file details, delete files, manage file visibility, and share files within a project. Each user has a storage quota that limits how much data they can store, and storage tools also expose quota and usage statistics. Files support visibility controls (public/private) and can be shared with other users with configurable permissions.
5470
+
5471
+ ## Tools Reference
5472
+
5473
+ ### storage_files_list
5474
+
5475
+ List files in storage for a project and user.
5476
+
5477
+ | Parameter | Type | Required | Description |
5478
+ |-----------|------|----------|-------------|
5479
+ | projectId | string | Yes | The project ID |
5480
+ | userId | string | Yes | The user ID whose files to list |
5481
+ | limit | integer | No | Number of files to return (1-100) |
5482
+ | offset | integer | No | Number of files to skip (min 0) |
5483
+
5484
+ ### storage_files_get
5485
+
5486
+ Get details of a specific file in storage.
5487
+
5488
+ | Parameter | Type | Required | Description |
5489
+ |-----------|------|----------|-------------|
5490
+ | projectId | string | Yes | The project ID |
5491
+ | userId | string | Yes | The user ID |
5492
+ | fileId | string | Yes | The file ID to retrieve |
5493
+
5494
+ ### storage_files_delete
5495
+
5496
+ Delete a specific file from storage.
5497
+
5498
+ | Parameter | Type | Required | Description |
5499
+ |-----------|------|----------|-------------|
5500
+ | projectId | string | Yes | The project ID |
5501
+ | userId | string | Yes | The user ID |
5502
+ | fileId | string | Yes | The file ID to delete |
5503
+
5504
+ ### storage_files_visibility
5505
+
5506
+ Update the visibility of a specific file.
5507
+
5508
+ | Parameter | Type | Required | Description |
5509
+ |-----------|------|----------|-------------|
5510
+ | projectId | string | Yes | The project ID |
5511
+ | userId | string | Yes | The user ID |
5512
+ | fileId | string | Yes | The file ID to update |
5513
+ | visibility | enum | Yes | \`"public"\` or \`"private"\` |
5514
+
5515
+ ### storage_files_share
5516
+
5517
+ Share a file with other users.
5518
+
5519
+ | Parameter | Type | Required | Description |
5520
+ |-----------|------|----------|-------------|
5521
+ | projectId | string | Yes | The project ID |
5522
+ | userId | string | Yes | The owner user ID |
5523
+ | fileId | string | Yes | The file ID to share |
5524
+ | userIds | string[] | Yes | Array of user IDs to share with |
5525
+ | permission | enum | No | \`"read"\` or \`"write"\` (defaults to read) |
5526
+
5527
+ ### storage_files_unshare
5528
+
5529
+ Remove file sharing for specific users.
5530
+
5531
+ | Parameter | Type | Required | Description |
5532
+ |-----------|------|----------|-------------|
5533
+ | projectId | string | Yes | The project ID |
5534
+ | userId | string | Yes | The owner user ID |
5535
+ | fileId | string | Yes | The file ID to unshare |
5536
+ | userIds | string[] | Yes | Array of user IDs to remove sharing for |
5537
+
5538
+ ### storage_quota_get
5539
+
5540
+ Get storage quota information for a user in a project.
5541
+
5542
+ | Parameter | Type | Required | Description |
5543
+ |-----------|------|----------|-------------|
5544
+ | projectId | string | Yes | The project ID |
5545
+ | userId | string | Yes | The user ID |
5546
+
5547
+ ### storage_quota_set
5548
+
5549
+ Set storage quota for a user in a project.
5550
+
5551
+ | Parameter | Type | Required | Description |
5552
+ |-----------|------|----------|-------------|
5553
+ | projectId | string | Yes | The project ID |
5554
+ | targetUserId | string | Yes | The user ID to set the quota for |
5555
+ | quotaBytes | integer | Yes | Quota size in bytes (min 0) |
5556
+
5557
+ ### storage_project_stats
5558
+
5559
+ Get storage statistics for a project.
5560
+
5561
+ | Parameter | Type | Required | Description |
5562
+ |-----------|------|----------|-------------|
5563
+ | projectId | string | Yes | The project ID |
5564
+
5565
+ ## Common Workflows
5566
+
5567
+ ### Uploading and Managing Files
5568
+
5569
+ 1. **List existing files** - Call \`storage_files_list\` with the \`projectId\` and \`userId\` to see what is already stored.
5570
+ 2. **Get file details** - Call \`storage_files_get\` with the \`fileId\` to inspect metadata such as size, type, and visibility.
5571
+ 3. **Delete unwanted files** - Call \`storage_files_delete\` to remove a file and free up quota.
5572
+
5573
+ ### Sharing Files
5574
+
5575
+ 1. **Share a file** - Call \`storage_files_share\` with the target \`userIds\` and an optional \`permission\` level (\`"read"\` or \`"write"\`).
5576
+ 2. **Revoke access** - Call \`storage_files_unshare\` with the \`userIds\` to remove their access.
5577
+ 3. **Set visibility** - Call \`storage_files_visibility\` to make a file \`"public"\` (accessible via URL) or \`"private"\` (requires authentication).
5578
+
5579
+ ### Managing Quotas
5580
+
5581
+ 1. **Check user quota** - Call \`storage_quota_get\` to see how much storage a user has used and their limit.
5582
+ 2. **Update quota** - Call \`storage_quota_set\` with \`targetUserId\` and \`quotaBytes\` to increase or decrease the allowed storage.
5583
+ 3. **Review project stats** - Call \`storage_project_stats\` to get an overview of total storage usage across the entire project.
5584
+
5585
+ ## Tips
5586
+
5587
+ - Use \`limit\` and \`offset\` in \`storage_files_list\` to paginate through large file collections.
5588
+ - Check \`storage_quota_get\` before uploading large files to verify sufficient remaining quota.
5589
+ - Set files to \`"public"\` visibility only when they need to be accessible without authentication (e.g., profile images, public assets).
5590
+ - When sharing files, prefer \`"read"\` permission unless the recipient needs to modify the file.
5591
+ - Use \`storage_project_stats\` to monitor overall project storage consumption and plan capacity.
5592
+ `;
5593
+ function registerStorageResources(server) {
5594
+ server.registerResource(
5595
+ "docs-storage",
5596
+ "spacelr://docs/storage",
5597
+ {
5598
+ title: "Storage - Spacelr Docs",
5599
+ description: "Documentation for file storage tools: listing, sharing, visibility, and quotas",
5600
+ mimeType: "text/markdown",
5601
+ annotations: {
5602
+ audience: ["assistant"],
5603
+ priority: 0.8
5604
+ }
5605
+ },
5606
+ async (uri) => ({
5607
+ contents: [{
5608
+ uri: uri.href,
5609
+ mimeType: "text/markdown",
5610
+ text: DOCS7
5611
+ }]
5612
+ })
5613
+ );
5614
+ }
5615
+
5616
+ // libs/mcp-server/src/resources/functions.ts
5617
+ var DOCS8 = `# Serverless Functions
5618
+
5619
+ ## Overview
5620
+
5621
+ Serverless functions let you run custom JavaScript code in an isolated V8 sandbox. Functions can be triggered manually, on a cron schedule, via webhook, or in response to platform events. Each function gets its own KV store, environment variables, and access to platform APIs (database, storage, email, notifications).
5622
+
5623
+ The runtime is **NOT Node.js** -- it is an isolated V8 sandbox (via isolated-vm). There is no \`require()\`, no static ES module \`import\` declarations, and no Node.js built-ins (\`fs\`, \`path\`, \`crypto\`, \`Buffer\`, \`process\`, etc.). Top-level \`await\` is supported, and local bundled modules can be loaded dynamically with \`await import('./lib.js')\`. All platform APIs are pre-injected globals.
5624
+
5625
+ ## Tools Reference
5626
+
5627
+ ### CRUD Operations
5628
+
5629
+ #### functions_list
5630
+
5631
+ List all functions for a project.
5632
+
5633
+ | Parameter | Type | Required | Description |
5634
+ |-----------|--------|----------|-------------|
5635
+ | projectId | string | Yes | Project ID |
5636
+
5637
+ ---
5638
+
5639
+ #### functions_get
5640
+
5641
+ Get details of a specific function.
5642
+
5643
+ | Parameter | Type | Required | Description |
5644
+ |------------|--------|----------|-------------|
5645
+ | projectId | string | Yes | Project ID |
5646
+ | functionId | string | Yes | Function ID |
5647
+
5648
+ ---
5649
+
5650
+ #### functions_create
5651
+
5652
+ Create a new serverless function in a project.
5653
+
5654
+ | Parameter | Type | Required | Description |
5655
+ |----------------|---------|----------|--------------------------------------------------|
5656
+ | projectId | string | Yes | Project ID |
5657
+ | name | string | Yes | Function name (1-255 chars) |
5658
+ | description | string | No | Description (max 1000 chars) |
5659
+ | entryPoint | string | No | Entry point file (max 255 chars, default: index.js) |
5660
+ | cronExpression | string | No | Cron expression for scheduled execution |
5661
+ | cronTimezone | string | No | Timezone for cron (e.g. "Europe/Berlin") |
5662
+ | timeout | integer | No | Execution timeout in ms (1000-120000, default: 30000) |
5663
+ | memoryLimitMb | integer | No | Memory limit in MB (16-512, default: 128) |
5664
+ | enabled | boolean | No | Whether the function is enabled |
5665
+
5666
+ ---
5667
+
5668
+ #### functions_update
5669
+
5670
+ Update an existing function. All fields except projectId and functionId are optional.
5671
+
5672
+ | Parameter | Type | Required | Description |
5673
+ |----------------|---------|----------|--------------------------------------------------|
5674
+ | projectId | string | Yes | Project ID |
5675
+ | functionId | string | Yes | Function ID |
5676
+ | name | string | No | Function name (1-255 chars) |
5677
+ | description | string | No | Description (max 1000 chars) |
5678
+ | entryPoint | string | No | Entry point file (max 255 chars) |
5679
+ | cronExpression | string | No | Cron expression for scheduled execution |
5680
+ | cronTimezone | string | No | Timezone for cron |
5681
+ | timeout | integer | No | Execution timeout in ms (1000-120000) |
5682
+ | memoryLimitMb | integer | No | Memory limit in MB (16-512) |
5683
+ | enabled | boolean | No | Whether the function is enabled |
5684
+
5685
+ ---
5686
+
5687
+ #### functions_delete
5688
+
5689
+ Delete a function and its associated cron job.
5690
+
5691
+ | Parameter | Type | Required | Description |
5692
+ |------------|--------|----------|-------------|
5693
+ | projectId | string | Yes | Project ID |
5694
+ | functionId | string | Yes | Function ID |
5695
+
5696
+ ---
5697
+
5698
+ ### Code & Deployments
5699
+
5700
+ #### functions_get_code
5701
+
5702
+ Get the deployed source code of a function with syntax-highlighted file contents.
5703
+
5704
+ | Parameter | Type | Required | Description |
5705
+ |------------|--------|----------|-------------|
5706
+ | projectId | string | Yes | Project ID |
5707
+ | functionId | string | Yes | Function ID |
5708
+
5709
+ ---
5710
+
5711
+ #### functions_deploy
5712
+
5713
+ Deploy code to a serverless function. Accepts one or more files as a record of filename to content. The files are bundled into a ZIP archive and uploaded.
5714
+
5715
+ | Parameter | Type | Required | Description |
5716
+ |------------|-------------------------|----------|--------------------------------------------------------------------------|
5717
+ | projectId | string | Yes | Project ID |
5718
+ | functionId | string | Yes | Function ID (from functions_create or functions_list) |
5719
+ | files | Record<string, string> | Yes | Map of filename to file content (e.g. \`{ "index.js": "..." }\`) |
5720
+ | entryPoint | string | No | Entry point file inside the bundle (default: "index.js", max 255 chars) |
5721
+
5722
+ **Example -- single file:**
5723
+ \`\`\`json
5724
+ { "files": { "index.js": "const data = await fetch('https://api.example.com'); console.log(data.body);" } }
5725
+ \`\`\`
5726
+
5727
+ **Example -- multiple files:**
5728
+ \`\`\`json
5729
+ { "files": { "index.js": "const { greet } = await import('./lib.js'); console.log(greet());", "lib.js": "export const greet = () => 'hello';" } }
5730
+ \`\`\`
5731
+
5732
+ ---
5733
+
5734
+ #### functions_deployments_list
5735
+
5736
+ List all deployments (versions) of a function.
5737
+
5738
+ | Parameter | Type | Required | Description |
5739
+ |------------|--------|----------|-------------|
5740
+ | projectId | string | Yes | Project ID |
5741
+ | functionId | string | Yes | Function ID |
5742
+
5743
+ ---
5744
+
5745
+ ### Execution
5746
+
5747
+ #### functions_trigger
5748
+
5749
+ Manually trigger a function execution.
5750
+
5751
+ | Parameter | Type | Required | Description |
5752
+ |------------|--------|----------|-------------|
5753
+ | projectId | string | Yes | Project ID |
5754
+ | functionId | string | Yes | Function ID |
5755
+
5756
+ ---
5757
+
5758
+ #### functions_executions_list
5759
+
5760
+ List recent executions of a function with status, duration, and logs.
5761
+
5762
+ | Parameter | Type | Required | Description |
5763
+ |------------|---------|----------|--------------------------------|
5764
+ | projectId | string | Yes | Project ID |
5765
+ | functionId | string | Yes | Function ID |
5766
+ | limit | integer | No | Max results to return (1-100) |
5767
+ | offset | integer | No | Number of results to skip (>= 0) |
5768
+
5769
+ ---
5770
+
5771
+ ### Webhooks
5772
+
5773
+ #### functions_enable_webhook
5774
+
5775
+ Enable webhook trigger for a function. Returns a one-time webhook secret.
5776
+
5777
+ | Parameter | Type | Required | Description |
5778
+ |------------|--------|----------|-------------|
5779
+ | projectId | string | Yes | Project ID |
5780
+ | functionId | string | Yes | Function ID |
5781
+
5782
+ ---
5783
+
5784
+ #### functions_regenerate_webhook_secret
5785
+
5786
+ Regenerate the webhook secret for a function. The old secret stops working immediately.
5787
+
5788
+ | Parameter | Type | Required | Description |
5789
+ |------------|--------|----------|-------------|
5790
+ | projectId | string | Yes | Project ID |
5791
+ | functionId | string | Yes | Function ID |
5792
+
5793
+ ---
5794
+
5795
+ #### functions_disable_webhook
5796
+
5797
+ Disable webhook trigger for a function. The webhook secret is deleted.
5798
+
5799
+ | Parameter | Type | Required | Description |
5800
+ |------------|--------|----------|-------------|
5801
+ | projectId | string | Yes | Project ID |
5802
+ | functionId | string | Yes | Function ID |
5803
+
5804
+ ---
5805
+
5806
+ ### Environment Variables
5807
+
5808
+ #### functions_get_env_vars
5809
+
5810
+ Get environment variables for a function (decrypted). Use these to store API keys and secrets.
5811
+
5812
+ | Parameter | Type | Required | Description |
5813
+ |------------|--------|----------|-------------|
5814
+ | projectId | string | Yes | Project ID |
5815
+ | functionId | string | Yes | Function ID |
5816
+
5817
+ ---
5818
+
5819
+ #### functions_set_env_vars
5820
+
5821
+ Set environment variables for a function. Merges with existing vars. Values are encrypted at rest.
5822
+
5823
+ | Parameter | Type | Required | Description |
5824
+ |------------|------------------------|----------|--------------------------------------------------|
5825
+ | projectId | string | Yes | Project ID |
5826
+ | functionId | string | Yes | Function ID |
5827
+ | variables | Record<string, string> | Yes | Key-value pairs to set (merged with existing) |
5828
+
5829
+ ---
5830
+
5831
+ ### KV Store
5832
+
5833
+ #### functions_kv_list
5834
+
5835
+ List KV store keys for a function.
5836
+
5837
+ | Parameter | Type | Required | Description |
5838
+ |------------|--------|----------|-------------|
5839
+ | projectId | string | Yes | Project ID |
5840
+ | functionId | string | Yes | Function ID |
5841
+
5842
+ ---
5843
+
5844
+ ## Sandbox API Quick Reference
5845
+
5846
+ These globals are available inside function code at runtime:
5847
+
5848
+ | API | Usage |
5849
+ |-----|-------|
5850
+ | \`console.log/warn/error/info()\` | Captured to execution logs (1MB buffer) |
5851
+ | \`await fetch(url, options?)\` | HTTP client. Returns \`{ status, headers, body }\` where body is a string. 10s timeout, 5MB limit. |
5852
+ | \`env.get(key)\` | Read environment variables (read-only) |
5853
+ | \`await kv.get(key)\` | Get a KV value (string or null) |
5854
+ | \`await kv.set(key, value, ttlSeconds?)\` | Set a KV value (256KB max, 30-day default TTL) |
5855
+ | \`await kv.delete(key)\` | Delete a KV key |
5856
+ | \`await kv.list(prefix?)\` | List KV keys (1000 max per function) |
5857
+ | \`await spacelr.db.collection(name).find(filter?, options?)\` | Query documents |
5858
+ | \`await spacelr.db.collection(name).insertOne(doc)\` | Insert one document |
5859
+ | \`await spacelr.db.collection(name).insertMany(docs)\` | Insert multiple documents |
5860
+ | \`await spacelr.storage.list/getInfo/getDownloadUrl()\` | Access project storage |
5861
+ | \`await spacelr.email.send({ to, template, variables })\` | Send template email |
5862
+ | \`await spacelr.email.sendRaw({ to, subject, html })\` | Send raw HTML email |
5863
+ | \`await spacelr.notifications.send({ userId, title, body, data? })\` | Send push notification |
5864
+ | \`await spacelr.notifications.sendMany({ userIds, title, body, data? })\` | Send to multiple users |
5865
+
5866
+ **Trigger context globals** (available depending on trigger type):
5867
+ - \`event\`: \`{ type, data, timestamp }\` -- for event-triggered executions
5868
+ - \`payload\`: \`{ ... }\` -- for webhook-triggered executions (the POST body)
5869
+
5870
+ ## Common Workflows
5871
+
5872
+ ### Creating and Deploying a Function
5873
+
5874
+ 1. **Create** the function with \`functions_create\` (provide name, optional timeout/memory settings).
5875
+ 2. **Deploy** code with \`functions_deploy\` -- pass your source files as a \`files\` record.
5876
+ 3. **Trigger** manually with \`functions_trigger\` to test.
5877
+ 4. **Check results** with \`functions_executions_list\` to see status, duration, and logs.
5878
+ 5. **Review code** with \`functions_get_code\` to verify what is deployed.
5879
+
5880
+ ### Scheduled Execution (Cron)
5881
+
5882
+ 1. Create or update the function with a \`cronExpression\` (e.g. \`"0 */6 * * *"\` for every 6 hours).
5883
+ 2. Optionally set \`cronTimezone\` (e.g. \`"Europe/Berlin"\`).
5884
+ 3. The function runs automatically on schedule when \`enabled\` is true.
5885
+
5886
+ ### Using the KV Store
5887
+
5888
+ Inside function code, use the \`kv\` global to persist data across executions:
5889
+ \`\`\`js
5890
+ const lastRun = await kv.get("lastRun");
5891
+ console.log("Last run:", lastRun);
5892
+ await kv.set("lastRun", new Date().toISOString());
5893
+ \`\`\`
5894
+
5895
+ Manage KV entries externally with \`functions_kv_list\`.
5896
+
5897
+ ### Setting Up Webhooks
5898
+
5899
+ 1. **Enable** the webhook with \`functions_enable_webhook\` -- save the returned secret.
5900
+ 2. **Call** the webhook endpoint: \`POST /api/v1/functions/{projectId}/{functionId}/invoke\` with header \`X-Webhook-Secret: <secret>\`.
5901
+ 3. Inside the function, read the POST body from the \`payload\` global.
5902
+ 4. **Rotate** the secret with \`functions_regenerate_webhook_secret\` (old secret stops immediately).
5903
+ 5. **Disable** with \`functions_disable_webhook\` when no longer needed.
5904
+
5905
+ ### Environment Variables
5906
+
5907
+ 1. **Set** variables with \`functions_set_env_vars\` (merges with existing vars, encrypted at rest).
5908
+ 2. **Read** inside function code with \`env.get("MY_API_KEY")\`.
5909
+ 3. **List** current variables with \`functions_get_env_vars\`.
5910
+
5911
+ ## Tips
5912
+
5913
+ - The runtime is an isolated V8 sandbox, not Node.js. Do not use \`require()\`, \`import\`, or Node.js built-ins.
5914
+ - \`fetch()\` returns \`{ status, headers, body }\` where \`body\` is always a **string**. Use \`JSON.parse(response.body)\` for JSON APIs.
5915
+ - If using \`spacelr.db\`, database rules must be set on the collection **before** the function writes to it. Without rules, inserts will fail with "Rule denied".
5916
+ - Store secrets in environment variables (\`functions_set_env_vars\`), not hardcoded in function code.
5917
+ - KV store values are capped at 256KB and 1000 keys per function with a 30-day default TTL.
5918
+ - Resource limits: 120s max timeout, 512MB max memory, 10MB max code bundle, 10 concurrent executions per project.
5919
+ - Use \`functions_deployments_list\` to see deployment history and roll back if needed.
5920
+ `;
5921
+ function registerFunctionResources(server) {
5922
+ server.registerResource(
5923
+ "docs-functions",
5924
+ "spacelr://docs/functions",
5925
+ {
5926
+ title: "Serverless Functions - Spacelr Docs",
5927
+ description: "Documentation for serverless function tools: deployment, execution, environment variables, KV store, and webhooks",
5928
+ mimeType: "text/markdown",
5929
+ annotations: {
5930
+ audience: ["assistant"],
5931
+ priority: 0.8
5932
+ }
5933
+ },
5934
+ async (uri) => ({
5935
+ contents: [{
5936
+ uri: uri.href,
5937
+ mimeType: "text/markdown",
5938
+ text: DOCS8
5939
+ }]
5940
+ })
5941
+ );
5942
+ }
5943
+
5944
+ // libs/mcp-server/src/resources/email-templates.ts
5945
+ var DOCS9 = `# Email Template Tools
5946
+
5947
+ ## Overview
5948
+
5949
+ The email template tools allow you to manage project-specific email templates in Spacelr. Templates use **MJML** for responsive email markup and **Handlebars** for variable interpolation. Each template has a \`type\` that identifies its purpose (e.g. "verify-email", "welcome", "invoice").
5950
+
5951
+ The system supports a layered resolution model: project-specific templates override system defaults. System default templates (those without a \`projectId\`) cannot be deleted.
5952
+
5953
+ ## Tools Reference
5954
+
5955
+ ### email_templates_list
5956
+
5957
+ List all email templates for a project (includes system defaults).
5958
+
5959
+ | Parameter | Type | Required | Description |
5960
+ |-----------|--------|----------|------------------------------------|
5961
+ | projectId | string | Yes | The project ID to list templates for |
5962
+
5963
+ **Returns:** An array of email template objects including both project-specific and system default templates.
5964
+
5965
+ ---
5966
+
5967
+ ### email_templates_get
5968
+
5969
+ Get a single email template by ID.
5970
+
5971
+ | Parameter | Type | Required | Description |
5972
+ |-----------|--------|----------|------------------------|
5973
+ | id | string | Yes | The email template ID |
5974
+
5975
+ **Returns:** The full email template object.
5976
+
5977
+ ---
5978
+
5979
+ ### email_templates_create
5980
+
5981
+ Create a new project-specific email template. The type identifies the template purpose (e.g. "verify-email", "welcome", "invoice").
5982
+
5983
+ | Parameter | Type | Required | Description |
5984
+ |------------|----------|----------|-----------------------------------------------------|
5985
+ | projectId | string | Yes | The project this template belongs to |
5986
+ | type | string | Yes | Template type identifier (e.g. "verify-email") |
5987
+ | name | string | Yes | Human-readable template name |
5988
+ | subject | string | Yes | Email subject line (supports Handlebars variables) |
5989
+ | mjmlSource | string | Yes | MJML markup for the email body |
5990
+ | variables | string[] | No | List of variable names used in the template |
5991
+ | isActive | boolean | No | Whether the template is active |
5992
+
5993
+ **Returns:** The created email template object.
5994
+
5995
+ ---
5996
+
5997
+ ### email_templates_update
5998
+
5999
+ Update an existing email template. At least one field must be provided.
6000
+
6001
+ | Parameter | Type | Required | Description |
6002
+ |------------|----------|----------|-----------------------------------------------------|
6003
+ | id | string | Yes | The email template ID to update |
6004
+ | name | string | No | Updated human-readable template name |
6005
+ | subject | string | No | Updated email subject line |
6006
+ | mjmlSource | string | No | Updated MJML markup |
6007
+ | variables | string[] | No | Updated list of variable names |
6008
+ | isActive | boolean | No | Updated active state |
6009
+
6010
+ **Returns:** The updated email template object.
6011
+
6012
+ ---
6013
+
6014
+ ### email_templates_delete
6015
+
6016
+ Delete an email template. System default templates cannot be deleted.
6017
+
6018
+ | Parameter | Type | Required | Description |
6019
+ |-----------|--------|----------|----------------------------------|
6020
+ | id | string | Yes | The email template ID to delete |
6021
+
6022
+ **Returns:** Confirmation message or the deleted template object.
6023
+
6024
+ ---
6025
+
6026
+ ### email_templates_preview
6027
+
6028
+ Preview a compiled email template. Renders MJML to HTML and applies Handlebars variables.
6029
+
6030
+ | Parameter | Type | Required | Description |
6031
+ |-----------|----------------------------|----------|------------------------------------------------------|
6032
+ | mjmlSource | string | Yes | MJML markup to render |
6033
+ | variables | Record<string, unknown> | No | Key-value map of Handlebars variables to interpolate |
6034
+
6035
+ **Returns:** The rendered HTML output of the template.
6036
+
6037
+ ## Common Workflows
6038
+
6039
+ ### Creating a Project-Specific Template
6040
+
6041
+ 1. Call \`email_templates_list\` with a \`projectId\` to see existing templates and system defaults.
6042
+ 2. Call \`email_templates_create\` with the project ID, a type, name, subject, and MJML source.
6043
+ 3. Use \`email_templates_preview\` to verify the rendered output before activating.
6044
+
6045
+ ### Previewing a Template
6046
+
6047
+ 1. Call \`email_templates_preview\` with your MJML source and an optional variables map.
6048
+ 2. Inspect the returned HTML to verify layout and variable substitution.
6049
+ 3. Iterate on the MJML source until the output looks correct.
6050
+
6051
+ ### Updating an Existing Template
6052
+
6053
+ 1. Call \`email_templates_get\` with the template ID to retrieve the current state.
6054
+ 2. Call \`email_templates_update\` with the ID and only the fields you want to change.
6055
+ 3. Use \`email_templates_preview\` to verify the changes render correctly.
6056
+
6057
+ ### Overriding a System Default
6058
+
6059
+ 1. Call \`email_templates_list\` with the project ID to find the system default you want to override.
6060
+ 2. Note the \`type\` of the system default template.
6061
+ 3. Call \`email_templates_create\` with the same \`type\` but your project ID and custom MJML source.
6062
+ 4. The project-specific template will now take priority over the system default.
6063
+
6064
+ ## Tips
6065
+
6066
+ - Use \`email_templates_preview\` to test MJML rendering without saving \u2014 this is the fastest way to iterate on template design.
6067
+ - The \`variables\` array on a template is informational \u2014 it documents which Handlebars variables the template expects but does not enforce them.
6068
+ - When previewing, pass sample data in the \`variables\` parameter to verify Handlebars interpolation works as expected.
6069
+ - System default templates (\`projectId: null\`) cannot be deleted. Create a project-specific template with the same type to override them.
6070
+ - MJML documentation is available at https://mjml.io/documentation/ for markup reference.
6071
+ `;
6072
+ function registerEmailTemplateResources(server) {
6073
+ server.registerResource(
6074
+ "docs-email-templates",
6075
+ "spacelr://docs/email-templates",
6076
+ {
6077
+ title: "Email Templates - Spacelr Docs",
6078
+ description: "Documentation for email template tools: create, update, preview, and manage templates",
6079
+ mimeType: "text/markdown",
6080
+ annotations: {
6081
+ audience: ["assistant"],
6082
+ priority: 0.6
6083
+ }
6084
+ },
6085
+ async (uri) => ({
6086
+ contents: [{
6087
+ uri: uri.href,
6088
+ mimeType: "text/markdown",
6089
+ text: DOCS9
6090
+ }]
6091
+ })
6092
+ );
6093
+ }
6094
+
6095
+ // libs/mcp-server/src/resources/cron-jobs.ts
6096
+ var DOCS10 = `# Cron Job Tools
6097
+
6098
+ ## Overview
6099
+
6100
+ The cron job tools allow you to schedule, manage, and monitor recurring tasks within a Spacelr project. Jobs can invoke a webhook URL or trigger a serverless function on a cron schedule. Each job tracks its execution history so you can inspect past runs and diagnose failures.
6101
+
6102
+ ## Tools Reference
6103
+
6104
+ ### cron_jobs_list
6105
+
6106
+ List all cron jobs for a project.
6107
+
6108
+ | Parameter | Type | Required | Description |
6109
+ |-----------|--------|----------|-------------|
6110
+ | projectId | string | Yes | Project ID |
6111
+
6112
+ ---
6113
+
6114
+ ### cron_jobs_get
6115
+
6116
+ Get a single cron job by ID.
6117
+
6118
+ | Parameter | Type | Required | Description |
6119
+ |-----------|--------|----------|-------------|
6120
+ | projectId | string | Yes | Project ID |
6121
+ | jobId | string | Yes | Cron job ID |
6122
+
6123
+ ---
6124
+
6125
+ ### cron_jobs_create
6126
+
6127
+ Create a new cron job. When type is \`webhook\`, \`url\` is required. When type is \`function\`, \`functionId\` is required. \`cronExpression\` uses 5-field cron format.
6128
+
6129
+ | Parameter | Type | Required | Description |
6130
+ |----------------|----------------------------|----------|-----------------------------------------------------------|
6131
+ | projectId | string | Yes | Project ID |
6132
+ | name | string | Yes | Display name for the job |
6133
+ | cronExpression | string | Yes | 5-field cron expression (e.g. \`0 0 * * *\`) |
6134
+ | timezone | string | No | IANA timezone (e.g. \`Europe/Berlin\`) |
6135
+ | type | \`"webhook"\` \\| \`"function"\` | No | Job type \u2014 determines whether \`url\` or \`functionId\` is used |
6136
+ | functionId | string | No | Function to invoke (required when type is \`function\`) |
6137
+ | url | string (URL) | No | Webhook URL to call (required when type is \`webhook\`) |
6138
+ | secret | string | No | Secret for webhook signature verification |
6139
+ | payload | Record<string, unknown> | No | JSON payload sent with each execution |
6140
+ | retryAttempts | integer (0-10) | No | Number of retry attempts on failure |
6141
+ | timeout | integer (1000-120000) | No | Execution timeout in milliseconds |
6142
+ | enabled | boolean | No | Whether the job is active (defaults to true) |
6143
+
6144
+ ---
6145
+
6146
+ ### cron_jobs_update
6147
+
6148
+ Update an existing cron job. At least one field (besides \`projectId\` and \`jobId\`) must be provided.
6149
+
6150
+ | Parameter | Type | Required | Description |
6151
+ |----------------|----------------------------|----------|-----------------------------------------------------------|
6152
+ | projectId | string | Yes | Project ID |
6153
+ | jobId | string | Yes | Cron job ID |
6154
+ | name | string | No | Updated display name |
6155
+ | cronExpression | string | No | Updated 5-field cron expression |
6156
+ | timezone | string | No | Updated IANA timezone |
6157
+ | type | \`"webhook"\` \\| \`"function"\` | No | Updated job type |
6158
+ | functionId | string | No | Updated function ID |
6159
+ | url | string (URL) | No | Updated webhook URL |
6160
+ | secret | string | No | Updated webhook secret |
6161
+ | payload | Record<string, unknown> | No | Updated JSON payload |
6162
+ | retryAttempts | integer (0-10) | No | Updated retry attempts |
6163
+ | timeout | integer (1000-120000) | No | Updated timeout in milliseconds |
6164
+ | enabled | boolean | No | Updated enabled state |
6165
+
6166
+ ---
6167
+
6168
+ ### cron_jobs_delete
6169
+
6170
+ Delete a cron job.
6171
+
6172
+ | Parameter | Type | Required | Description |
6173
+ |-----------|--------|----------|-------------|
6174
+ | projectId | string | Yes | Project ID |
6175
+ | jobId | string | Yes | Cron job ID |
6176
+
6177
+ ---
6178
+
6179
+ ### cron_jobs_trigger
6180
+
6181
+ Manually trigger a cron job execution outside of its schedule.
6182
+
6183
+ | Parameter | Type | Required | Description |
6184
+ |-----------|--------|----------|-------------|
6185
+ | projectId | string | Yes | Project ID |
6186
+ | jobId | string | Yes | Cron job ID |
6187
+
6188
+ ---
6189
+
6190
+ ### cron_jobs_toggle
6191
+
6192
+ Toggle a cron job enabled or disabled.
6193
+
6194
+ | Parameter | Type | Required | Description |
6195
+ |-----------|---------|----------|------------------------------------|
6196
+ | projectId | string | Yes | Project ID |
6197
+ | jobId | string | Yes | Cron job ID |
6198
+ | enabled | boolean | Yes | \`true\` to enable, \`false\` to disable |
6199
+
6200
+ ---
6201
+
6202
+ ### cron_jobs_executions
6203
+
6204
+ List execution history for a cron job.
6205
+
6206
+ | Parameter | Type | Required | Description |
6207
+ |-----------|-------------------|----------|--------------------------------|
6208
+ | projectId | string | Yes | Project ID |
6209
+ | jobId | string | Yes | Cron job ID |
6210
+ | limit | integer (1-100) | No | Max number of results |
6211
+ | offset | integer (>= 0) | No | Number of results to skip |
6212
+
6213
+ ---
6214
+
6215
+ ### cron_jobs_list_all
6216
+
6217
+ List all cron jobs across projects (admin overview).
6218
+
6219
+ | Parameter | Type | Required | Description |
6220
+ |-----------|--------|----------|---------------------------------------|
6221
+ | projectId | string | No | Filter by project ID (omit for all) |
6222
+
6223
+ ---
6224
+
6225
+ ### cron_jobs_status
6226
+
6227
+ Get the cron queue status (no parameters).
6228
+
6229
+ | Parameter | Type | Required | Description |
6230
+ |-----------|------|----------|-------------|
6231
+
6232
+ This tool takes no parameters. It returns the current state of the cron processing queue.
6233
+
6234
+ ## Common Workflows
6235
+
6236
+ ### Creating a Webhook Cron Job
6237
+
6238
+ 1. Call \`cron_jobs_create\` with \`projectId\`, \`name\`, \`cronExpression\`, \`type: "webhook"\`, and \`url\`.
6239
+ 2. Optionally set \`secret\` for signature verification and \`payload\` for a custom body.
6240
+ 3. The job starts running on schedule immediately unless \`enabled\` is set to \`false\`.
6241
+
6242
+ ### Creating a Function Cron Job
6243
+
6244
+ 1. Call \`cron_jobs_create\` with \`projectId\`, \`name\`, \`cronExpression\`, \`type: "function"\`, and \`functionId\`.
6245
+ 2. Optionally pass \`payload\` to provide input data to the function.
6246
+ 3. Use \`retryAttempts\` and \`timeout\` to control failure handling.
6247
+
6248
+ ### Toggling a Job On/Off
6249
+
6250
+ 1. Call \`cron_jobs_toggle\` with the \`projectId\`, \`jobId\`, and \`enabled: false\` to pause or \`enabled: true\` to resume.
6251
+
6252
+ ### Checking Execution History
6253
+
6254
+ 1. Call \`cron_jobs_executions\` with \`projectId\` and \`jobId\`.
6255
+ 2. Use \`limit\` and \`offset\` to paginate through results.
6256
+ 3. Each execution record contains status, timestamps, and any error details.
6257
+
6258
+ ### Monitoring the Queue
6259
+
6260
+ 1. Call \`cron_jobs_status\` (no parameters) to inspect the queue health and processing state.
6261
+ 2. Call \`cron_jobs_list_all\` to get an admin-level overview of all jobs across projects.
6262
+
6263
+ ## Tips
6264
+
6265
+ - **Cron expression format:** Uses standard 5-field syntax \u2014 \`minute hour day-of-month month day-of-week\`. For example, \`*/15 * * * *\` runs every 15 minutes, \`0 9 * * 1-5\` runs at 09:00 on weekdays.
6266
+ - **Timezone:** Defaults to UTC if omitted. Use IANA timezone names such as \`America/New_York\` or \`Europe/Berlin\`.
6267
+ - **Retry and timeout:** \`retryAttempts\` (0-10) controls how many times a failed execution is retried. \`timeout\` (1000-120000 ms) sets the maximum execution duration before the run is aborted.
6268
+ - **Manual trigger:** Use \`cron_jobs_trigger\` to run a job immediately for testing \u2014 it does not affect the regular schedule.
6269
+ - **At least one field:** When calling \`cron_jobs_update\`, you must supply at least one field to change beyond \`projectId\` and \`jobId\`.
6270
+ `;
6271
+ function registerCronJobResources(server) {
6272
+ server.registerResource(
6273
+ "docs-cron-jobs",
6274
+ "spacelr://docs/cron-jobs",
6275
+ {
6276
+ title: "Cron Jobs - Spacelr Docs",
6277
+ description: "Documentation for cron job tools: scheduling, execution, and monitoring",
6278
+ mimeType: "text/markdown",
6279
+ annotations: {
6280
+ audience: ["assistant"],
6281
+ priority: 0.6
6282
+ }
6283
+ },
6284
+ async (uri) => ({
6285
+ contents: [{
6286
+ uri: uri.href,
6287
+ mimeType: "text/markdown",
6288
+ text: DOCS10
6289
+ }]
6290
+ })
6291
+ );
6292
+ }
6293
+
6294
+ // libs/mcp-server/src/resources/webhooks.ts
6295
+ var DOCS11 = `# Webhook Tools
6296
+
6297
+ ## Overview
6298
+
6299
+ The webhook tools let you manage event subscriptions for a project. Webhooks send HTTP POST requests to a configured URL whenever specific events occur \u2014 such as user sign-ups, database writes, or file uploads. You can create, update, test, and monitor webhooks and their delivery history entirely through these tools.
6300
+
6301
+ ## Event Types
6302
+
6303
+ The following event types are available when creating or updating a webhook:
6304
+
6305
+ | Category | Event |
6306
+ |-----------|------------------------------------|
6307
+ | User | \`user.created\` |
6308
+ | User | \`user.updated\` |
6309
+ | User | \`user.deleted\` |
6310
+ | User | \`user.login\` |
6311
+ | User | \`user.email_verified\` |
6312
+ | User | \`user.password_reset_requested\` |
6313
+ | User | \`user.password_reset\` |
6314
+ | User | \`user.2fa_verified\` |
6315
+ | Database | \`database.insert\` |
6316
+ | Database | \`database.update\` |
6317
+ | Database | \`database.delete\` |
6318
+ | Storage | \`storage.upload\` |
6319
+ | Storage | \`storage.delete\` |
6320
+ | Project | \`project.created\` |
6321
+ | Project | \`project.updated\` |
6322
+
6323
+ ## Tools Reference
6324
+
6325
+ ### webhooks_list
6326
+
6327
+ List all webhooks for a project.
6328
+
6329
+ | Parameter | Type | Required | Description |
6330
+ |-----------|--------|----------|-------------|
6331
+ | projectId | string | Yes | Project ID |
6332
+
6333
+ **Returns:** Array of webhook objects.
6334
+
6335
+ ---
6336
+
6337
+ ### webhooks_get
6338
+
6339
+ Get a single webhook by ID.
6340
+
6341
+ | Parameter | Type | Required | Description |
6342
+ |-----------|--------|----------|-------------|
6343
+ | projectId | string | Yes | Project ID |
6344
+ | webhookId | string | Yes | Webhook ID |
6345
+
6346
+ **Returns:** The webhook object.
6347
+
6348
+ ---
6349
+
6350
+ ### webhooks_create
6351
+
6352
+ Create a new webhook for a project.
6353
+
6354
+ > **WARNING:** The response includes a secret that will be visible in the conversation context.
6355
+
6356
+ | Parameter | Type | Required | Description |
6357
+ |-------------|-------------------------------|----------|---------------------------------------------------|
6358
+ | projectId | string | Yes | Project ID |
6359
+ | url | string (URL) | Yes | Endpoint URL that will receive POST requests |
6360
+ | events | string[] (min 1) | Yes | Array of event types to subscribe to (see above) |
6361
+ | description | string | No | Human-readable description of the webhook |
6362
+ | headers | Record<string, string> | No | Custom HTTP headers sent with each delivery |
6363
+ | active | boolean | No | Whether the webhook is active |
6364
+
6365
+ **Returns:** The created webhook object including its secret.
6366
+
6367
+ ---
6368
+
6369
+ ### webhooks_update
6370
+
6371
+ Update an existing webhook. At least one optional field must be provided.
6372
+
6373
+ | Parameter | Type | Required | Description |
6374
+ |-------------|-------------------------------|----------|---------------------------------------------------|
6375
+ | projectId | string | Yes | Project ID |
6376
+ | webhookId | string | Yes | Webhook ID |
6377
+ | url | string (URL) | No | Updated endpoint URL |
6378
+ | events | string[] (min 1) | No | Updated array of event types |
6379
+ | description | string | No | Updated description |
6380
+ | headers | Record<string, string> | No | Updated custom HTTP headers |
6381
+ | active | boolean | No | Enable or disable the webhook |
6382
+
6383
+ **Returns:** The updated webhook object.
6384
+
6385
+ ---
6386
+
6387
+ ### webhooks_delete
6388
+
6389
+ Delete a webhook.
6390
+
6391
+ | Parameter | Type | Required | Description |
6392
+ |-----------|--------|----------|-------------|
6393
+ | projectId | string | Yes | Project ID |
6394
+ | webhookId | string | Yes | Webhook ID |
6395
+
6396
+ **Returns:** Confirmation that the webhook was deleted.
6397
+
6398
+ ---
6399
+
6400
+ ### webhooks_test
6401
+
6402
+ Send a test ping to a webhook to verify the endpoint is reachable.
6403
+
6404
+ | Parameter | Type | Required | Description |
6405
+ |-----------|--------|----------|-------------|
6406
+ | projectId | string | Yes | Project ID |
6407
+ | webhookId | string | Yes | Webhook ID |
6408
+
6409
+ **Returns:** The test delivery result.
6410
+
6411
+ ---
6412
+
6413
+ ### webhooks_deliveries
6414
+
6415
+ List webhook delivery logs for a project. Optionally filter by a specific webhook.
6416
+
6417
+ | Parameter | Type | Required | Description |
6418
+ |-----------|---------|----------|--------------------------------------|
6419
+ | projectId | string | Yes | Project ID |
6420
+ | webhookId | string | No | Filter deliveries to this webhook |
6421
+ | limit | integer | No | Number of results (1-100) |
6422
+ | offset | integer | No | Offset for pagination (min 0) |
6423
+
6424
+ **Returns:** Array of delivery log entries.
6425
+
6426
+ ---
6427
+
6428
+ ### webhooks_delivery_retry
6429
+
6430
+ Retry a failed webhook delivery.
6431
+
6432
+ | Parameter | Type | Required | Description |
6433
+ |------------|--------|----------|----------------|
6434
+ | projectId | string | Yes | Project ID |
6435
+ | deliveryId | string | Yes | Delivery ID |
6436
+
6437
+ **Returns:** The retry delivery result.
6438
+
6439
+ ## Common Workflows
6440
+
6441
+ ### Creating a Webhook
6442
+
6443
+ 1. Call \`webhooks_create\` with the \`projectId\`, target \`url\`, and at least one event type in \`events\`.
6444
+ 2. Store the returned secret securely \u2014 it is used to verify delivery signatures on the receiving end.
6445
+ 3. Use \`webhooks_test\` to send a test ping and confirm the endpoint responds correctly.
6446
+
6447
+ ### Testing a Webhook
6448
+
6449
+ 1. Call \`webhooks_test\` with the \`projectId\` and \`webhookId\`.
6450
+ 2. Check the response for the HTTP status code returned by the endpoint.
6451
+ 3. If the test fails, verify the URL is reachable and returns a 2xx status.
6452
+
6453
+ ### Checking Delivery History
6454
+
6455
+ 1. Call \`webhooks_deliveries\` with the \`projectId\` to list recent deliveries.
6456
+ 2. Optionally pass \`webhookId\` to filter to a specific webhook.
6457
+ 3. Use \`limit\` and \`offset\` for pagination through large delivery logs.
6458
+
6459
+ ### Retrying a Failed Delivery
6460
+
6461
+ 1. Identify the failed delivery ID from \`webhooks_deliveries\`.
6462
+ 2. Call \`webhooks_delivery_retry\` with the \`projectId\` and \`deliveryId\`.
6463
+ 3. Check the result to confirm the retry succeeded.
6464
+
6465
+ ### Disabling a Webhook
6466
+
6467
+ 1. Call \`webhooks_update\` with \`active\` set to \`false\` to pause deliveries without deleting the webhook.
6468
+ 2. Set \`active\` back to \`true\` to re-enable it later.
6469
+
6470
+ ## Tips
6471
+
6472
+ - Always call \`webhooks_test\` after creating or updating a webhook to verify the endpoint works.
6473
+ - Use \`description\` to document the purpose of each webhook for easier management.
6474
+ - Custom \`headers\` can be used to pass authentication tokens or API keys to the receiving endpoint.
6475
+ - The \`events\` array must contain at least one event type \u2014 an empty array is not allowed.
6476
+ - When updating a webhook, only the fields you provide will be changed; omitted fields remain unchanged.
6477
+ - Use \`webhooks_deliveries\` to monitor for failures and \`webhooks_delivery_retry\` to re-send missed events.
6478
+ - The webhook secret from \`webhooks_create\` is only shown once \u2014 treat it like a password.
6479
+ `;
6480
+ function registerWebhookResources(server) {
6481
+ server.registerResource(
6482
+ "docs-webhooks",
6483
+ "spacelr://docs/webhooks",
6484
+ {
6485
+ title: "Webhooks - Spacelr Docs",
6486
+ description: "Documentation for webhook tools: event subscriptions, deliveries, and testing",
6487
+ mimeType: "text/markdown",
6488
+ annotations: {
6489
+ audience: ["assistant"],
6490
+ priority: 0.6
6491
+ }
6492
+ },
6493
+ async (uri) => ({
6494
+ contents: [{
6495
+ uri: uri.href,
6496
+ mimeType: "text/markdown",
6497
+ text: DOCS11
6498
+ }]
6499
+ })
6500
+ );
6501
+ }
6502
+
6503
+ // libs/mcp-server/src/resources/notifications.ts
6504
+ var DOCS12 = `# Notification Tools
6505
+
6506
+ ## Overview
6507
+
6508
+ The notification tools manage web push notifications for Spacelr projects. The system supports three push providers \u2014 VAPID (Web Push), FCM (Firebase Cloud Messaging), and APNS (Apple Push Notification Service). Notification content is driven by Handlebars-based templates that can be customised per project, with system defaults as fallbacks.
6509
+
6510
+ ## Tools Reference
6511
+
6512
+ ### Templates
6513
+
6514
+ #### notification_templates_list
6515
+
6516
+ List all notification templates for a project (includes system defaults).
6517
+
6518
+ | Parameter | Type | Required | Description |
6519
+ |-----------|--------|----------|-------------|
6520
+ | projectId | string | Yes | The project ID |
6521
+
6522
+ ---
6523
+
6524
+ #### notification_templates_get
6525
+
6526
+ Get a single notification template by ID.
6527
+
6528
+ | Parameter | Type | Required | Description |
6529
+ |-----------|--------|----------|-------------|
6530
+ | id | string | Yes | The template ID |
6531
+
6532
+ ---
6533
+
6534
+ #### notification_templates_create
6535
+
6536
+ Create a new project-specific notification template. Variables use Handlebars syntax in \`titleTemplate\` and \`bodyTemplate\`.
6537
+
6538
+ | Parameter | Type | Required | Description |
6539
+ |---------------|----------|----------|-------------|
6540
+ | projectId | string | Yes | The project ID |
6541
+ | type | string | Yes | Template type identifier |
6542
+ | name | string | Yes | Human-readable template name |
6543
+ | titleTemplate | string | Yes | Handlebars template for the notification title |
6544
+ | bodyTemplate | string | Yes | Handlebars template for the notification body |
6545
+ | icon | string | No | URL of the notification icon |
6546
+ | defaultUrl | string | No | Default click-through URL |
6547
+ | variables | string[] | No | List of variable names used in the templates |
6548
+ | isActive | boolean | No | Whether the template is active |
6549
+
6550
+ ---
6551
+
6552
+ #### notification_templates_update
6553
+
6554
+ Update an existing notification template. At least one field must be provided.
6555
+
6556
+ | Parameter | Type | Required | Description |
6557
+ |---------------|----------|----------|-------------|
6558
+ | id | string | Yes | The template ID |
6559
+ | name | string | No | Human-readable template name |
6560
+ | titleTemplate | string | No | Handlebars template for the notification title |
6561
+ | bodyTemplate | string | No | Handlebars template for the notification body |
6562
+ | icon | string | No | URL of the notification icon |
6563
+ | defaultUrl | string | No | Default click-through URL |
6564
+ | variables | string[] | No | List of variable names used in the templates |
6565
+ | isActive | boolean | No | Whether the template is active |
6566
+
6567
+ ---
6568
+
6569
+ #### notification_templates_delete
6570
+
6571
+ Delete a project notification template override (reverts to system default).
6572
+
6573
+ | Parameter | Type | Required | Description |
6574
+ |-----------|--------|----------|-------------|
6575
+ | id | string | Yes | The template ID |
6576
+
6577
+ ---
6578
+
6579
+ #### notification_templates_preview
6580
+
6581
+ Preview a compiled notification template with Handlebars variables applied.
6582
+
6583
+ | Parameter | Type | Required | Description |
6584
+ |---------------|-------------------------|----------|-------------|
6585
+ | titleTemplate | string | Yes | Handlebars template for the title |
6586
+ | bodyTemplate | string | Yes | Handlebars template for the body |
6587
+ | variables | Record<string, string> | Yes | Key-value map of variable values to substitute |
6588
+
6589
+ ---
6590
+
6591
+ ### Configuration
6592
+
6593
+ #### notification_config_get
6594
+
6595
+ Get push notification provider configuration for a project (VAPID, FCM, APNS).
6596
+
6597
+ > **WARNING:** The response may include sensitive credentials that will be visible in the conversation context.
6598
+
6599
+ | Parameter | Type | Required | Description |
6600
+ |-----------|--------|----------|-------------|
6601
+ | projectId | string | Yes | The project ID |
6602
+
6603
+ ---
6604
+
6605
+ #### notification_config_update
6606
+
6607
+ Update push notification provider configuration. Supports VAPID, FCM, and APNS providers.
6608
+
6609
+ > **WARNING:** \`privateKey\` and \`serviceAccountJson\` values are sensitive credentials that will be visible in the conversation context.
6610
+
6611
+ | Parameter | Type | Required | Description |
6612
+ |-----------|--------|----------|-------------|
6613
+ | projectId | string | Yes | The project ID |
6614
+ | vapid | object | No | VAPID (Web Push) configuration |
6615
+ | fcm | object | No | Firebase Cloud Messaging configuration |
6616
+ | apns | object | No | Apple Push Notification Service configuration |
6617
+
6618
+ **vapid object:**
6619
+
6620
+ | Field | Type | Required | Description |
6621
+ |------------|---------|----------|-------------|
6622
+ | publicKey | string | No | VAPID public key |
6623
+ | privateKey | string | No | VAPID private key |
6624
+ | subject | string | No | VAPID subject (usually a mailto: or URL) |
6625
+ | enabled | boolean | No | Whether VAPID is enabled |
6626
+
6627
+ **fcm object:**
6628
+
6629
+ | Field | Type | Required | Description |
6630
+ |--------------------|---------|----------|-------------|
6631
+ | serviceAccountJson | string | No | Firebase service account JSON |
6632
+ | enabled | boolean | No | Whether FCM is enabled |
6633
+
6634
+ **apns object:**
6635
+
6636
+ | Field | Type | Required | Description |
6637
+ |------------|---------|----------|-------------|
6638
+ | keyId | string | No | APNS key ID |
6639
+ | teamId | string | No | Apple Developer team ID |
6640
+ | privateKey | string | No | APNS private key |
6641
+ | bundleId | string | No | App bundle identifier |
6642
+ | production | boolean | No | Use production APNS environment |
6643
+ | enabled | boolean | No | Whether APNS is enabled |
6644
+
6645
+ ---
6646
+
6647
+ #### notification_config_delete
6648
+
6649
+ Delete push notification provider configuration. Specify a provider to delete only that one, or omit to delete all.
6650
+
6651
+ | Parameter | Type | Required | Description |
6652
+ |-----------|--------|----------|-------------|
6653
+ | projectId | string | Yes | The project ID |
6654
+ | provider | enum | No | Provider to delete: \`vapid\`, \`fcm\`, or \`apns\`. Omit to delete all. |
6655
+
6656
+ ---
6657
+
6658
+ #### notification_config_generate_vapid
6659
+
6660
+ Generate a new VAPID key pair for web push notifications.
6661
+
6662
+ > **WARNING:** The private key will be visible in the conversation context.
6663
+
6664
+ This tool takes no parameters.
6665
+
6666
+ **Returns:** An object with \`publicKey\` and \`privateKey\` strings.
6667
+
6668
+ ---
6669
+
6670
+ ### Sending
6671
+
6672
+ #### notifications_send
6673
+
6674
+ Send a push notification to selected users.
6675
+
6676
+ | Parameter | Type | Required | Description |
6677
+ |-----------|----------|----------|-------------|
6678
+ | projectId | string | Yes | The project ID |
6679
+ | userIds | string[] | Yes | Array of user IDs to notify (min 1) |
6680
+ | title | string | Yes | Notification title |
6681
+ | body | string | Yes | Notification body text |
6682
+ | icon | string | No | URL of the notification icon |
6683
+ | url | string | No | Click-through URL |
6684
+
6685
+ ---
6686
+
6687
+ #### notifications_broadcast
6688
+
6689
+ Broadcast a push notification to all subscribed users in a project.
6690
+
6691
+ | Parameter | Type | Required | Description |
6692
+ |-----------|--------|----------|-------------|
6693
+ | projectId | string | Yes | The project ID |
6694
+ | title | string | Yes | Notification title |
6695
+ | body | string | Yes | Notification body text |
6696
+ | icon | string | No | URL of the notification icon |
6697
+ | url | string | No | Click-through URL |
6698
+
6699
+ ## Common Workflows
6700
+
6701
+ ### Setting Up VAPID (Web Push)
6702
+
6703
+ 1. Call \`notification_config_generate_vapid\` to generate a new key pair.
6704
+ 2. Call \`notification_config_update\` with the generated keys and a \`subject\` (e.g. \`mailto:admin@example.com\`) under the \`vapid\` object, setting \`enabled: true\`.
6705
+ 3. Verify the configuration with \`notification_config_get\`.
6706
+
6707
+ ### Creating a Custom Template
6708
+
6709
+ 1. Call \`notification_templates_list\` to see existing templates and system defaults.
6710
+ 2. Call \`notification_templates_create\` with a \`type\`, \`name\`, and Handlebars templates for title and body. For example: \`titleTemplate: "Hello {{userName}}"\`, \`bodyTemplate: "{{message}}"\`.
6711
+ 3. Use \`notification_templates_preview\` to verify the template renders correctly with sample variables.
6712
+
6713
+ ### Sending Notifications to Specific Users
6714
+
6715
+ 1. Ensure push configuration is set up (see VAPID workflow above).
6716
+ 2. Call \`notifications_send\` with the \`projectId\`, an array of \`userIds\`, and the notification \`title\` and \`body\`.
6717
+ 3. Optionally include an \`icon\` URL and a click-through \`url\`.
6718
+
6719
+ ### Broadcasting to All Users
6720
+
6721
+ 1. Ensure push configuration is set up.
6722
+ 2. Call \`notifications_broadcast\` with the \`projectId\`, \`title\`, and \`body\`.
6723
+ 3. The notification will be delivered to all users with active push subscriptions in the project.
6724
+
6725
+ ## Tips
6726
+
6727
+ - Always set up provider configuration (\`notification_config_update\`) before attempting to send notifications.
6728
+ - Use \`notification_templates_preview\` to test Handlebars templates before creating them \u2014 this avoids broken notifications reaching users.
6729
+ - Deleting a project template override with \`notification_templates_delete\` reverts to the system default; it does not remove the template entirely.
6730
+ - The \`notification_config_generate_vapid\` tool generates keys on the server \u2014 you do not need to generate them locally.
6731
+ - Be cautious with \`notifications_broadcast\` as it reaches all subscribed users in the project. Prefer \`notifications_send\` for targeted delivery.
6732
+ - Provider credentials (private keys, service account JSON) are sensitive. Avoid sharing conversations that contain these values.
6733
+ `;
6734
+ function registerNotificationResources(server) {
6735
+ server.registerResource(
6736
+ "docs-notifications",
6737
+ "spacelr://docs/notifications",
6738
+ {
6739
+ title: "Notifications - Spacelr Docs",
6740
+ description: "Documentation for push notification tools: configuration, templates, sending, and broadcasting",
6741
+ mimeType: "text/markdown",
6742
+ annotations: {
6743
+ audience: ["assistant"],
6744
+ priority: 0.7
6745
+ }
6746
+ },
6747
+ async (uri) => ({
6748
+ contents: [{
6749
+ uri: uri.href,
6750
+ mimeType: "text/markdown",
6751
+ text: DOCS12
6752
+ }]
6753
+ })
6754
+ );
6755
+ }
6756
+
6757
+ // libs/mcp-server/src/resources/audit-logs.ts
6758
+ var DOCS13 = `# Audit Logs
6759
+
6760
+ ## Overview
6761
+
6762
+ Audit logs provide a detailed, immutable record of actions performed within a project. Every significant operation (user creation, client modification, database changes, etc.) is captured with metadata including the actor, timestamp, entity type, and action performed. Use the audit log tools to investigate activity, troubleshoot issues, and maintain compliance.
6763
+
6764
+ ## Tools Reference
6765
+
6766
+ ### audit_logs_list
6767
+
6768
+ List audit logs for a project with optional filters.
6769
+
6770
+ | Parameter | Type | Required | Description |
6771
+ |---------------|--------|----------|-------------|
6772
+ | \`projectId\` | string | Yes | The project ID to query audit logs for |
6773
+ | \`entityType\` | enum | No | Filter by entity type. One of: \`user\`, \`client\`, \`project\`, \`auth\`, \`database\`, \`storage\` |
6774
+ | \`action\` | string | No | Filter by action name (e.g. \`create\`, \`update\`, \`delete\`) |
6775
+ | \`startDate\` | string | No | ISO 8601 datetime. Only return logs on or after this date |
6776
+ | \`endDate\` | string | No | ISO 8601 datetime. Only return logs on or before this date |
6777
+ | \`limit\` | number | No | Number of entries to return (1-100) |
6778
+ | \`offset\` | number | No | Number of entries to skip (min 0), for pagination |
6779
+
6780
+ ### audit_logs_get
6781
+
6782
+ Retrieve a single audit log entry by its ID.
6783
+
6784
+ | Parameter | Type | Required | Description |
6785
+ |--------------|--------|----------|-------------|
6786
+ | \`projectId\` | string | Yes | The project ID the log belongs to |
6787
+ | \`logId\` | string | Yes | The ID of the audit log entry |
6788
+
6789
+ ## Common Workflows
6790
+
6791
+ ### List recent activity for a project
6792
+
6793
+ Call \`audit_logs_list\` with just the \`projectId\` to see the most recent log entries.
6794
+
6795
+ ### Filter by entity type
6796
+
6797
+ Pass \`entityType\` to narrow results, e.g. set \`entityType\` to \`user\` to see only user-related events.
6798
+
6799
+ ### Filter by date range
6800
+
6801
+ Provide \`startDate\` and/or \`endDate\` as ISO 8601 strings to restrict the time window:
6802
+ - \`startDate\`: \`"2025-01-01T00:00:00Z"\`
6803
+ - \`endDate\`: \`"2025-01-31T23:59:59Z"\`
6804
+
6805
+ ### Paginate through results
6806
+
6807
+ Use \`limit\` and \`offset\` together. For example, to fetch the second page of 25 results, set \`limit\` to 25 and \`offset\` to 25.
6808
+
6809
+ ### View details of a specific entry
6810
+
6811
+ Use \`audit_logs_get\` with the \`logId\` obtained from a list result to retrieve the full entry with all metadata.
6812
+
6813
+ ## Tips
6814
+
6815
+ - **Entity types**: \`user\`, \`client\`, \`project\`, \`auth\`, \`database\`, \`storage\` cover the main domains. Use them to focus queries on the area you care about.
6816
+ - **Date filtering**: Both \`startDate\` and \`endDate\` accept ISO 8601 datetime strings (e.g. \`2025-06-15T08:00:00Z\`). You can use one or both to define a range.
6817
+ - **Pagination**: The default result set may be limited. Always use \`limit\` and \`offset\` when you need to retrieve large numbers of entries.
6818
+ - **Action names**: Actions are free-form strings. Common values include \`create\`, \`update\`, \`delete\`, \`login\`, and \`logout\`, but the exact values depend on the operations your project performs.
6819
+ `;
6820
+ function registerAuditLogResources(server) {
6821
+ server.registerResource(
6822
+ "docs-audit-logs",
6823
+ "spacelr://docs/audit-logs",
6824
+ {
6825
+ title: "Audit Logs - Spacelr Docs",
6826
+ description: "Documentation for audit log tools: listing and viewing audit entries",
6827
+ mimeType: "text/markdown",
6828
+ annotations: {
6829
+ audience: ["assistant"],
6830
+ priority: 0.5
6831
+ }
6832
+ },
6833
+ async (uri) => ({
6834
+ contents: [{
6835
+ uri: uri.href,
6836
+ mimeType: "text/markdown",
6837
+ text: DOCS13
6838
+ }]
6839
+ })
6840
+ );
6841
+ }
6842
+
6843
+ // libs/mcp-server/src/resources/best-practices.ts
6844
+ var DOCS14 = `# Best Practices & Setup Guide
6845
+
6846
+ This guide covers how to set up and use the Spacelr MCP server effectively. Follow these steps to ensure a smooth experience.
6847
+
6848
+ ## Initial Setup \u2014 Credentials
6849
+
6850
+ The MCP server needs valid credentials to interact with the Spacelr API. There are two ways to authenticate:
6851
+
6852
+ ### Option A: Use the Spacelr CLI (Recommended)
6853
+
6854
+ Install and log in via the CLI \u2014 this creates the credentials file automatically:
6855
+
6856
+ \`\`\`bash
6857
+ npx @spacelr/cli login
6858
+ \`\`\`
6859
+
6860
+ This opens a browser for OAuth authentication and stores credentials at:
6861
+ - **Global:** \`~/.spacelr/credentials.json\`
6862
+ - **Project-scoped:** \`<projectDir>/.spacelr/credentials.json\` (if \`spacelr.json\` exists)
6863
+
6864
+ ### Option B: Use the auth_login Tool
6865
+
6866
+ If the CLI is not available, use the \`auth_login\` MCP tool directly with email and password. The MCP server stores the returned token automatically.
6867
+
6868
+ ### Credential File Structure
6869
+
6870
+ \`\`\`json
6871
+ {
6872
+ "accessToken": "eyJ...",
6873
+ "refreshToken": "refresh_...",
6874
+ "expiresAt": 1712000000000,
6875
+ "apiUrl": "https://api.spacelr.com/api/v1"
6876
+ }
6877
+ \`\`\`
6878
+
6879
+ ### Credential Lookup Order
6880
+
6881
+ 1. \`SPACELR_AUTH_TOKEN\` environment variable (highest priority)
6882
+ 2. Project-scoped: \`<projectDir>/.spacelr/credentials.json\` (if \`spacelr.json\` found)
6883
+ 3. Global fallback: \`~/.spacelr/credentials.json\`
6884
+
6885
+ ### Security
6886
+
6887
+ - Credential files are created with restrictive permissions (\`0o600\` \u2014 owner read/write only)
6888
+ - The \`.spacelr/\` directory is automatically added to \`.gitignore\` to prevent accidental commits
6889
+ - Token refresh happens automatically when the token is within 60 seconds of expiration
6890
+
6891
+ ## Project Configuration \u2014 spacelr.json
6892
+
6893
+ Create a \`spacelr.json\` file in your project root to scope credentials and set defaults:
6894
+
6895
+ \`\`\`json
6896
+ {
6897
+ "projectId": "your-project-id",
6898
+ "apiUrl": "https://api.spacelr.com/api/v1",
6899
+ "hosting": {
6900
+ "directory": "./dist"
6901
+ }
6902
+ }
6903
+ \`\`\`
6904
+
6905
+ You can also create this file using the CLI:
6906
+
6907
+ \`\`\`bash
6908
+ npx @spacelr/cli init
6909
+ \`\`\`
6910
+
6911
+ This will prompt you to select a project and configure hosting settings.
6912
+
6913
+ **Benefits of having spacelr.json:**
6914
+ - Credentials are stored per-project in \`.spacelr/credentials.json\` (not globally)
6915
+ - The \`projectId\` is available as a default for tools that require it
6916
+ - Team members get consistent project configuration
6917
+
6918
+ ## Environment Variables
6919
+
6920
+ For CI/CD pipelines or automated environments, use environment variables instead of credential files:
6921
+
6922
+ | Variable | Purpose |
6923
+ |----------|---------|
6924
+ | \`SPACELR_AUTH_TOKEN\` | Override authentication token directly |
6925
+ | \`SPACELR_API_URL\` | Override API endpoint URL |
6926
+ | \`SPACELR_CLIENT_ID\` | Override OAuth client ID |
6927
+ | \`SPACELR_PROJECT_ID\` | Override default project ID |
6928
+
6929
+ \`SPACELR_AUTH_TOKEN\` takes highest priority and bypasses all file-based credential resolution.
6930
+
6931
+ ## Best Practices
6932
+
6933
+ ### Authentication
6934
+ - Always verify your session with \`auth_me\` before starting work
6935
+ - Use project-scoped credentials when working within a specific project
6936
+ - For CI/CD, prefer \`SPACELR_AUTH_TOKEN\` over stored credentials
6937
+ - Token refresh is automatic \u2014 no manual re-authentication needed under normal conditions
6938
+
6939
+ ### Database
6940
+ - **Rules-first approach:** Always define security rules for a collection before inserting data
6941
+ - Without rules, all operations are denied by the \`$other\` catch-all rule
6942
+ - Use \`database_rules_set\` to define collection rules \u2014 this automatically creates the collection
6943
+ - Read the database documentation at \`spacelr://docs/database\` for the full rules syntax
6944
+
6945
+ ### Storage
6946
+ - Use presigned URLs for large file uploads from client applications
6947
+ - Manage user quotas proactively to prevent storage overflows
6948
+
6949
+ ### Functions
6950
+ - Functions run in a V8 sandbox \u2014 no Node.js APIs, no require/import
6951
+ - Always deploy after updating function code
6952
+ - Use the KV store for persistent state between executions
6953
+
6954
+ ### Hosting
6955
+ - Upload all files before activating a deployment
6956
+ - Use SPA mode for single-page applications to handle client-side routing
6957
+
6958
+ ## Recommended Workflow for AI Assistants
6959
+
6960
+ When first connecting to a Spacelr project, follow this sequence:
6961
+
6962
+ 1. **Check for spacelr.json** \u2014 Look in the current directory and parent directories. If it exists, note the \`projectId\`.
6963
+
6964
+ 2. **Verify session** \u2014 Call \`auth_me\` to check if credentials are valid.
6965
+
6966
+ 3. **Authenticate if needed** \u2014 If not authenticated, guide the user through \`auth_login\` or suggest running \`npx @spacelr/cli login\`.
6967
+
6968
+ 4. **Identify the project** \u2014 Use \`projects_list\` to find available projects, or use the \`projectId\` from \`spacelr.json\`.
6969
+
6970
+ 5. **Read relevant documentation** \u2014 Before performing tasks, read the appropriate docs resource:
6971
+ - \`spacelr://docs/database\` for database operations
6972
+ - \`spacelr://docs/storage\` for file management
6973
+ - \`spacelr://docs/functions\` for serverless functions
6974
+ - \`spacelr://docs/hosting\` for static site deployment
6975
+ - See \`spacelr://docs/getting-started\` for the full list
6976
+
6977
+ 6. **Execute the task** \u2014 Use the documented tools with correct parameters.
6978
+
6979
+ ## Available Documentation Resources
6980
+
6981
+ For the full list of documentation resources, read \`spacelr://docs/getting-started\`.
6982
+ `;
6983
+ function registerBestPracticeResources(server) {
6984
+ server.registerResource(
6985
+ "docs-best-practices",
6986
+ "spacelr://docs/best-practices",
6987
+ {
6988
+ title: "Best Practices & Setup - Spacelr Docs",
6989
+ description: "Setup guide and best practices: credential configuration, spacelr.json, environment variables, and recommended workflows for AI assistants",
6990
+ mimeType: "text/markdown",
6991
+ annotations: {
6992
+ audience: ["assistant"],
6993
+ priority: 0.95
6994
+ }
6995
+ },
6996
+ async (uri) => ({
6997
+ contents: [
6998
+ {
6999
+ uri: uri.href,
7000
+ mimeType: "text/markdown",
7001
+ text: DOCS14
7002
+ }
7003
+ ]
7004
+ })
7005
+ );
7006
+ }
7007
+
7008
+ // libs/mcp-server/src/resources/index.ts
7009
+ function registerAllResources(server) {
7010
+ registerGettingStartedResources(server);
7011
+ registerAuthResources(server);
7012
+ registerProjectResources(server);
7013
+ registerClientResources(server);
7014
+ registerDatabaseResources(server);
7015
+ registerHostingResources(server);
7016
+ registerStorageResources(server);
7017
+ registerFunctionResources(server);
7018
+ registerEmailTemplateResources(server);
7019
+ registerCronJobResources(server);
7020
+ registerWebhookResources(server);
7021
+ registerNotificationResources(server);
7022
+ registerAuditLogResources(server);
7023
+ registerBestPracticeResources(server);
7024
+ }
7025
+
4307
7026
  // libs/mcp-server/src/index.ts
4308
7027
  async function main() {
4309
7028
  const config = await loadConfig();
@@ -4314,6 +7033,7 @@ async function main() {
4314
7033
  });
4315
7034
  registerAllTools(server, api);
4316
7035
  registerAllPrompts(server);
7036
+ registerAllResources(server);
4317
7037
  const transport = new StdioServerTransport();
4318
7038
  await server.connect(transport);
4319
7039
  const shutdown = async () => {