Saltar al contenido principal

Fyso MCP Guide for Builders

Connect your AI agent to Fyso and build a complete data backend in minutes.

What is Fyso MCP?

Fyso exposes a Model Context Protocol (MCP) server that lets AI agents (Claude Desktop, Claude Code, or any MCP-compatible client) create entities, manage records, define business rules, and deploy static sites — all through natural language.

Quick Start: Claude Desktop (< 3 min)

1. Get your API key

Sign up at app.fyso.dev and create a tenant. Your API key will be shown during onboarding.

2. Configure Claude Desktop

Open your Claude Desktop config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
  • Linux: ~/.config/Claude/claude_desktop_config.json

Add the Fyso MCP server:

{
"mcpServers": {
"fyso": {
"command": "npx",
"args": ["-y", "@fyso/mcp-server"],
"env": {
"FYSO_API_KEY": "fyso_ak_your_key_here",
"FYSO_API_URL": "https://app.fyso.dev/api"
}
}
}
}

3. Start building

Restart Claude Desktop. You now have access to 47 MCP tools. Try:

"List my tenants and select one"

"Create an entity called 'customers' with name, email, phone, and address fields"

"Add a business rule: when email changes, convert to lowercase"

Quick Start: Claude Code

claude mcp add fyso -- npx -y @fyso/mcp-server \
--env FYSO_API_KEY=fyso_ak_your_key_here \
--env FYSO_API_URL=https://app.fyso.dev/api

Or add to your project's .mcp.json:

{
"mcpServers": {
"fyso": {
"command": "npx",
"args": ["-y", "@fyso/mcp-server"],
"env": {
"FYSO_API_KEY": "fyso_ak_your_key_here",
"FYSO_API_URL": "https://app.fyso.dev/api"
}
}
}
}

Example: Build a Project Management System

Here's a step-by-step conversation with Claude using Fyso MCP:

Step 1: Create entities

"Create these entities for a project management system:

  • projects: name (text, required), description (textarea), status (select: active/completed/archived), deadline (date)
  • tasks: title (text, required), description (textarea), status (select: todo/in-progress/done), priority (select: low/medium/high/critical), project_id (relation to projects)
  • team_members: name (text, required), email (email, required, unique), role (select: developer/designer/manager)"

Claude will call generate_entity three times, creating all entities with proper field types.

Step 2: Add business rules

"Add a rule to tasks: when status changes to 'done', validate that the title is not empty"

// Claude creates this rule via create_business_rule:
{
"triggerType": "field_change",
"triggerFields": ["status"],
"ruleDsl": {
"validate": [{
"id": "title_required_on_done",
"condition": "status != 'done' or len(title) > 0",
"message": "Tasks marked as done must have a title",
"severity": "error"
}]
}
}

Step 3: Add sample data

"Create 3 sample projects and 5 tasks distributed across them"

Claude calls create_record for each record, automatically linking tasks to projects via project_id.

Step 4: Query your data

"Show me all tasks with priority 'high' sorted by deadline"

// Claude calls query_records:
{
"entityName": "tasks",
"filter": "priority = high",
"orderBy": "deadline",
"orderDir": "asc"
}

Step 5: Generate an API client

"Generate a TypeScript API client for my project management entities"

Claude calls generate_api_client and returns ready-to-use TypeScript code with full types.

Multi-Tenancy: One Backend, Multiple Clients

Fyso isolates data per tenant using PostgreSQL schemas. Each tenant gets its own entities, records, rules, and users.

Create tenants for your clients

> "List my tenants"
> "Select tenant 'acme-corp'"
> "Import the freelancer prebuild for this tenant"

Switch between tenants

> "Select tenant 'client-a'"
> "Create a customer record: name 'John Doe', email 'john@example.com'"
> "Now select tenant 'client-b'"
> "List all customers" // Returns client-b's customers, not client-a's

Tenant users

Each tenant can have users with roles:

RolePermissions
ownerFull control over everything
adminManage users, settings, and data
memberCreate and edit records
viewerRead-only access
> "Create a user in tenant 'acme-corp': email 'maria@acme.com', name 'Maria Garcia', role 'member'"

Channels: Share Tools Between Tenants

Channels let you expose your tenant's data as tools that other tenants (or agents) can use.

Publish your tenant as a channel

> "Publish my tenant as a channel called 'acme-products' with tags 'retail' and 'products'"

Define custom tools

> "Define a channel tool called 'search-products' that queries the products entity with semantic search"

This creates a tool other agents can discover and use:

// Other agents can call:
execute_channel_tool({
channel_slug: "acme-products",
tool_name: "search-products",
params: { query: "organic coffee beans", limit: 5 }
})

Set permissions

> "Set channel permissions: default read-only, but allow readwrite on the 'orders' entity"

Prebuilds: Import Ready-Made Templates

Fyso includes prebuild packages with entities, fields, rules, and sample data:

PrebuildEntitiesDescription
freelancer5 (clientes, proyectos, facturas, lineas_factura, pagos)Freelance/consulting business
taller5 (clientes, vehiculos, ordenes, servicios, inventario)Auto repair shop
tienda5 (clientes, categorias, productos, pedidos, lineas_pedido)Retail store

Import via MCP

> "Import the taller prebuild for my tenant"

This creates all entities with proper field types, business rules (including cross-entity lookups and aggregates), and optionally seed data.

Export and reimport

> "Export my tenant's metadata"
// Returns JSON with all entities, fields, and rules

> "Select tenant 'new-client'"
> "Import this metadata into the new tenant"

API Client Generator

Generate a complete TypeScript client for your entities:

> "Generate a TypeScript API client for all my entities"

Returns ready-to-use code:

import { FysoClient } from './fyso-client';

const client = new FysoClient({
baseUrl: 'https://app.fyso.dev/api',
apiKey: 'fyso_ak_...',
});

// Full type safety
const customers = await client.customers.list({ limit: 20 });
const customer = await client.customers.create({
name: 'Acme Corp',
email: 'contact@acme.com',
});
await client.customers.update(customer.id, { phone: '+34 912345678' });
await client.customers.delete(customer.id);

Available MCP Tools (47)

Tenant Management

ToolDescription
list_tenantsList all accessible tenants
select_tenantSelect active tenant for the session

Entity Management

ToolDescription
generate_entityCreate entity from JSON definition
list_entitiesList entities in current tenant
get_entity_schemaGet field definitions for an entity
publish_entityPublish a draft entity
delete_entityDelete an entity (irreversible)
list_entity_changesShow draft changes vs published
export_metadataExport all entities, fields, and rules
import_metadataImport metadata into tenant

Record CRUD

ToolDescription
query_recordsList/filter/search/sort records
create_recordCreate a new record
update_recordUpdate an existing record
delete_recordDelete a record

Custom Fields

ToolDescription
manage_custom_fieldsAdd, update, delete, or list custom fields

Business Rules

ToolDescription
generate_business_ruleGenerate rule from natural language
create_business_ruleCreate rule with DSL (compute, validate, transform, actions)
list_business_rulesList rules for an entity
get_business_ruleGet rule details and DSL
test_business_ruleTest rule with sample data in sandbox
publish_business_rulePublish a draft rule
delete_business_ruleDelete a rule

API & Client

ToolDescription
get_rest_api_specGet REST API documentation with curl examples
generate_api_clientGenerate TypeScript API client with types

User Management

ToolDescription
create_userCreate tenant user (owner/admin/member/viewer)
list_usersList users in current tenant

Channels

ToolDescription
search_channelsDiscover public channels
get_channel_infoGet channel details
get_my_channelGet your tenant's channel
get_channel_toolsList tools available in a channel
publish_channelMake your tenant discoverable
update_channelUpdate channel metadata
unpublish_channelRemove from public catalog
set_channel_permissionsConfigure read/readwrite access
define_channel_toolCreate custom tool with DSL
update_channel_toolModify a custom tool
remove_channel_toolDelete a custom tool
execute_channel_toolUse a tool from another channel

Static Sites

ToolDescription
deploy_static_siteDeploy to <subdomain>.sites.fyso.dev
list_static_sitesList your deployments
delete_static_siteRemove a deployment

Bot Identity

ToolDescription
register_botRegister a bot with a secret key
identify_botAuthenticate as a registered bot
list_botsList your registered bots
whoami_botCheck current bot identity
revoke_botDeactivate a bot

Business Rules DSL Reference

Rules use a declarative DSL with four sections:

compute — Calculate fields

{
"compute": {
"total": { "type": "formula", "expression": "cantidad * precio" },
"descuento": {
"type": "conditional",
"conditions": [{ "when": "total > 1000", "then": "total * 0.1" }],
"default": "0"
},
"precio_producto": {
"type": "lookup",
"entity": "productos",
"matchField": "id",
"matchValue": "producto_id",
"resultField": "precio"
},
"total_pedidos": {
"type": "aggregate",
"entity": "pedidos",
"aggregateOp": "count",
"filter": { "cliente_id": "id" }
}
}
}

validate — Check constraints

{
"validate": [{
"id": "email_required",
"condition": "len(email) > 0",
"message": "Email is required",
"severity": "error"
}]
}

transform — Format fields

{
"transform": {
"email": { "type": "lowercase" },
"nombre": { "type": "trim" },
"total": { "type": "round", "decimals": 2 }
}
}

actions — Cross-entity side effects (after_save only)

{
"actions": [{
"type": "update_related",
"entity": "post",
"recordId": "post_id",
"data": {
"comments_count": {
"type": "aggregate",
"entity": "comment",
"aggregateOp": "count",
"filter": { "post_id": "post_id" }
}
}
}]
}

Trigger types

TriggerWhen it fires
field_changeWhen specified fields change
before_saveBefore the record is persisted
after_saveAfter the record is persisted (supports actions)

REST API

For programmatic access outside MCP, use the REST API directly:

# List records
curl -H "Authorization: Bearer $API_KEY" \
"https://app.fyso.dev/api/entities/customers/records?limit=10"

# Create a record
curl -X POST -H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Acme Corp", "email": "contact@acme.com"}' \
"https://app.fyso.dev/api/entities/customers/records"

# Semantic search
curl -H "Authorization: Bearer $API_KEY" \
"https://app.fyso.dev/api/entities/products/records/search/semantic?q=organic+coffee&limit=5"

Important: Entity fields are nested inside record.data, not at the top level:

{
"id": "abc-123",
"data": {
"name": "Acme Corp",
"email": "contact@acme.com"
}
}

Access fields as record.data.email, not record.email.

Environment Variables

VariableDefaultDescription
FYSO_API_KEYYour tenant API key
FYSO_API_URLhttp://localhost:3001/apiFyso API base URL
MCP_SERVER_PORT3002HTTP server port (SSE mode)
MCP_SERVER_URLhttp://localhost:3002/mcpMCP server URL (for JWT audience)

Common Patterns

1. Scaffold a complete app backend

> "Create entities for an e-commerce app: products (name, description, price, stock, category),
> orders (customer_name, email, status, total), order_lines (order_id, product_id, quantity, subtotal)"
> "Add a rule to order_lines: when quantity or product changes, lookup product price and calculate subtotal"
> "Add an after_save rule to order_lines: count lines per order and update order total"
> "Generate a TypeScript API client"
> "Deploy a landing page for my store"

2. Import a prebuild and customize

> "Import the tienda prebuild"
> "Add a 'loyalty_points' number field to customers"
> "Add a rule: when a pedido is created, increment customer loyalty_points by 1"

3. Multi-agent collaboration via channels

// Agent A (data owner):
> "Publish my tenant as 'product-catalog' channel"
> "Define a tool 'search-products' using semantic search on products entity"

// Agent B (consumer):
> "Search channels tagged 'products'"
> "Execute 'search-products' on 'product-catalog' channel with query 'wireless headphones'"

Troubleshooting

ProblemSolution
Entity not foundRun list_entities to check entity names. Names are lowercase with underscores.
Tenant not selectedRun select_tenant before any data operations.
401 UnauthorizedCheck your FYSO_API_KEY is correct and not expired.
Business rule validation failedUse test_business_rule to debug rules with sample data.
Login returns HTML instead of JSONUse POST /api/auth/tenant/login (note the /api prefix).
Record fields are nullAccess fields via record.data.fieldName, not record.fieldName.
Creado con Fyso