Selvans
БесплатноНе проверенA framework that makes any web application natively operable by AI agents through the Model Context Protocol (MCP), replacing browser automation with structured
Описание
A framework that makes any web application natively operable by AI agents through the Model Context Protocol (MCP), replacing browser automation with structured UI semantic trees and typed backend operations.
README
selvans is a framework that makes any web application natively operable by AI agents through the Model Context Protocol (MCP).
Instead of using browser automation, AI agents connect directly to your application through a structured protocol — observing the UI semantic tree and calling typed tools to interact with it.
How It Works
External AI (Claude Desktop, Cursor…)
│ MCP / SSE
▼
┌──────────────────┐
│ selvans-core │ ← Hub service (WebSocket + MCP server + admin UI)
└──────┬─────┬─────┘
│ WS │ WS
┌────┘ └────┐
▼ ▼
Angular App Python Backend
(selvans- (selvans-
angular) python)
- selvans-core is the central hub. It exposes an MCP server (SSE) that external AI clients connect to, and a WebSocket endpoint that your frontend and backend connect to.
- selvans-angular integrates into your Angular app. It registers a semantic UI tree and built-in tools (
click_element,form_input,get_page_state…) with the Core. - selvans-python integrates into your Python/FastAPI backend. It registers typed service operations with the Core — tool schemas and argument validation are derived from your type hints by the official MCP SDK.
- The AI calls tools and operations through the Core, which routes them to the right app in real time.
Repository Structure
selvans/
├── packages/
│ ├── core/ # Hub service + Docker image (Python module: selvans_core)
│ ├── lib/ # Client libraries
│ │ ├── selvans-angular/ # Angular library (npm)
│ │ ├── selvans-python/ # Python client library (PyPI)
│ │ └── selvans-java/ # Java library (planned)
│ ├── demo/ # Demo stack
│ │ ├── selvans-angular-demo/ # Angular demo app
│ │ ├── selvans-python-demo/ # FastAPI demo backend
│ │ └── docker-compose.yml # Demo Docker Compose
│ ├── setup/ # npm installer for the Claude plugin (WIP)
│ └── claude-plugin/ # Claude plugin: agents/commands/skills (WIP)
└── .github/workflows/ # CI (docker-images.yml, release.yml)
There is no root Nx/pnpm workspace — packages are organized by shippable artifact and each one builds, tests and ships on its own.
Quick Start
The demo stack runs entirely in Docker (only Docker required — no Node/pnpm on the host). The Core is consumed as a published image; until it exists on Docker Hub, build it locally first:
# 1. Build the Core image locally (one-off, until it's published to Docker Hub)
docker build -t gabrieleconsonni/selvans-core:latest packages/core
# 2. Start the stack: Core (:8080) + Python demo (:8001) + Angular dev server (:4200, live-reload)
docker compose -f packages/demo/docker-compose.yml up -d --build
Open http://localhost:4200 — the selvans-panel should show "connected".
Live-reload: the Angular source is bind-mounted into the container. Saving a file in
packages/demo/selvans-angular-demo/orpackages/lib/selvans-angular/triggers an automatic browser update (~1 s latency due to polling on Docker Desktop Windows).First startup: the Angular container build (in-container
npm install+ esbuild) takes ~90–180 s.
Prod-like (Angular built and served via nginx instead of the live-reload dev server):
docker compose -f packages/demo/docker-compose.yml --profile full up -d --build
Note:
selvans-angular-dev(default profile, live-reload) andselvans-angular-demo(profilefull, nginx) both bind port 4200 — never run both at once.
Teardown (stop + wipe volumes):
docker compose -f packages/demo/docker-compose.yml down -v
See [[Getting-started]] in the wiki for the full guide and troubleshooting.
Manual start
1. Start the Core
# Run the Core on its own (local build)
docker compose -f packages/core/docker-compose.yml up --build
# Admin UI → http://localhost:8080/ui
# MCP SSE → http://localhost:8080/mcp/sse
2. Integrate the Angular Frontend
npm install selvans-angular
// app.module.ts
import { SelvansModule } from 'selvans-angular';
@NgModule({
imports: [
SelvansModule.forRoot({
coreUrl: 'http://localhost:8080',
appId: 'my-app'
})
]
})
export class AppModule {}
Mark your components with semantic directives:
<main [SelvansNode]="{ id: 'main', template: 'layout', description: 'Main content area' }">
<form [SelvansNode]="{ id: 'login-form', template: 'form', description: 'User login form' }">
<input [SelvansTarget]="'email-input'" type="email" />
<button [SelvansTarget]="'submit-btn'">Login</button>
</form>
</main>
3. Integrate the Python Backend
pip install selvans
# main.py
from typing import Literal
from selvans import SelvansBeApp, SelvansBeConfig, SelvansService, operation
class TaskService(SelvansService):
name = "tasks"
description = "Task management"
@operation("list", description="List tasks, optionally filtered by status")
async def list_tasks(self, status: Literal["pending", "completed"] | None = None) -> list[dict]:
return await db.list_tasks(status=status)
@operation("create", description="Create a new task")
async def create_task(self, title: str, priority: Literal["high", "medium", "low"] = "medium") -> dict:
return await db.create_task(title, priority)
surface = SelvansBeApp(SelvansBeConfig(core_url="http://localhost:8080"))
surface.register(TaskService())
app = surface.create_app()
Type hints drive the AI-facing schema: Literal[...] becomes a JSON Schema enum,
X | None an optional field, and out-of-range arguments are rejected before your
method runs.
4. Connect an AI Client
Add the Core's MCP endpoint to your AI client (e.g. Claude Desktop claude_desktop_config.json):
{
"mcpServers": {
"selvans": {
"url": "http://localhost:8080/mcp/sse"
}
}
}
The AI can now observe your app's UI and call your backend operations directly.
When the Core runs with authentication enabled (
Selvans_AUTH_MODE=enforce), the client must present a bearer token ("headers": { "Authorization": "Bearer <token>" }) and only sees the tools it is authorized for — see Authentication.
Run the Full Demo
docker compose -f packages/demo/docker-compose.yml up -d --build
# → Core :8080 + Python demo :8001 + Angular dev container :4200 (live-reload)
Or prod-like, with Angular served via nginx:
docker compose -f packages/demo/docker-compose.yml --profile full up -d --build
# → Core :8080 + Python demo :8001 + Angular nginx :4200 (static bundle)
| Service | URL | Mode |
|---|---|---|
| selvans-core | http://localhost:8080 | both |
| Admin UI | http://localhost:8080/ui | both |
| MCP SSE endpoint | http://localhost:8080/mcp/sse | both |
| Python demo backend | http://localhost:8001 | both |
| Angular demo frontend | http://localhost:4200 | dev (live-reload) / prod-like (nginx) |
Note:
selvans-angular-dev(dev, live-reload) andselvans-angular-demo(profilefull, nginx) both bind port 4200 — do not start them together.
Packages
| Package | Description | Docs |
|---|---|---|
selvans-angular |
Angular library — semantic UI tree + built-in tools | docs |
selvans-python |
Python library — FastAPI integration + service operations | docs |
selvans-core |
Hub service — MCP server + WebSocket hub + admin UI | docs |
Built-in Frontend Tools
The Angular library registers these tools automatically:
| Tool | Description |
|---|---|
get_page_state |
Returns current URL, title, and visible text |
navigate |
Navigate to a route by path |
get_elements |
List all elements marked with [SelvansTarget] |
click_element |
Click an element by its target ID |
form_input |
Read or set the value of a form field by target ID |
In-App AI Chat (built-in)
External MCP clients (Claude Desktop, Cursor) run the AI in a separate window. For a chat that lives next to the UI it drives, the Core ships a built-in agent loop — no AI vendor SDK, just plain HTTP to the provider you configure.
┌──────────────── selvans-core ────────────────┐
Browser │ WS /chat/ws → ChatOrchestrator (agent loop) │ ──HTTP──▶ LLM
chat │ │ router.dispatch() │ (Anthropic /
panel / │ ▼ │ OpenAI / Ollama)
console │ connected apps (FE + BE) via WS │
└───────────────────────────────────────────────┘
The orchestrator asks the model for tool calls, runs them through the same
ToolRouter that MCP clients use, and feeds results back until the model
answers.
The browser talks to it over a stateful, streaming WebSocket (/chat/ws):
the Core owns the conversation, so what the user types reaches the model and the
loop streams back live — the assistant's narration, each tool call and its
result, then the reply. The chat is a real-time mirror of the agent, and
because the Core (not an external MCP client) drives the loop, the browser →
model → browser round-trip is just a normal bidirectional socket. A stateless
POST /chat (whole transcript in, final reply out) remains for simple callers.
Two surfaces are exposed over it:
- Frontend panel — drop
<selvans-chat />into your Angular app. The chat is scoped to that app's tools, so the assistant operates the UI the user is looking at, live. - Multi-app console —
http://localhost:8080/ui/console. One chat, an app-switcher across every registered app, and the selected app's UI embedded in an iframe beside it.
Configure the provider via env (see .env.example) — the Core reaches it over
HTTP, so switching is only a matter of these values:
AI_PROVIDER=ollama # ollama | openai | anthropic
OLLAMA_MODEL=qwen2.5:7b-instruct
# OPENAI_API_KEY=… OPENAI_MODEL=gpt-4o-mini
# ANTHROPIC_API_KEY=… ANTHROPIC_MODEL=claude-sonnet-4-20250514
With ollama (the default) no API key is needed — use a model that supports
tool calling. If the selected provider is missing its key, the chat returns a
clear, actionable error (an error frame over the socket, or an error body from
POST /chat) and the rest of the Core keeps working.
Authentication
App-to-Core authentication is available as an opt-in first step (phase 0-1 of the
auth design). Apps authenticate to the
Core with a shared-secret token bound to their appId, and the Core refuses to let
one app hijack another's live appId.
Configured via env on the Core:
# off (default) | permissive (verify + log, don't block) | enforce (reject)
Selvans_AUTH_MODE=enforce
# per-app shared secrets, keyed by appId
Selvans_APP_TOKENS='{"demo-backend":"change-me"}'
Each app then presents its token — SelvansBeConfig(token=…) (Python),
SelvansModule.forRoot({ token: … }) (Angular). With AUTH_MODE=off behaviour is
unchanged, so existing deployments are unaffected. Roll out with permissive to
observe violations in the logs before switching to enforce.
The same AUTH_MODE also governs AI/MCP clients: each client is given a bearer
token and an allow-list of apps, so it can only see and call the tools it is
authorized for (tool calls are attributed to the real client id, not a shared
constant):
Selvans_MCP_CLIENTS='{"claude-desktop":{"token":"change-me","allow":["demo-backend"]}}'
In
enforcemode you must configure bothSelvans_APP_TOKENSandSelvans_MCP_CLIENTS, otherwise apps / AI clients are rejected.
End-user identity
The AI can act on behalf of an end user: it presents the user's token in the
X-Selvans-User header, the Core verifies it (HS256 JWT when Selvans_USER_JWT_SECRET
is set; otherwise an opaque, unverified subject id), and propagates the identity to
your app on every call. Every tool call is then attributable to a real user in the
telemetry — closing the "we don't know which user made a request" gap.
Selvans_USER_JWT_SECRET=change-me # verify the user JWT (omit for opaque dev mode)
Your backend reads the caller without changing operation signatures:
from selvans import operation, current_user_id
@operation("list", description="List the current user's tasks")
async def list_tasks(self) -> list[dict]:
return await db.list_tasks(owner=current_user_id()) # None if no user propagated
Angular receives the same context on the toolCall$ stream. Identity is propagated
and audited regardless of AUTH_MODE; it is about attribution, not access control,
so an absent/invalid user token never blocks a call (it is logged).
License
Distributed under the Apache 2.0 license — see LICENSE and NOTICE.
Установка Selvans
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/gabrieleakeron/selvansFAQ
Selvans MCP бесплатный?
Да, Selvans MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для Selvans?
Нет, Selvans работает без API-ключей и переменных окружения.
Selvans — hosted или self-hosted?
Доступен hosted-вариант: Unyly запускает сервер в облаке, локальная установка не обязательна.
Как установить Selvans в Claude Desktop, Claude Code или Cursor?
Открой Selvans на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
LibreOffice Tools
Enables AI agents to read, write, and edit Office documents via LibreOffice with token-efficient design. Supports multiple formats including DOCX, XLSX, PPTX, a
автор: passerbyflutterdannote/figma-use
Full Figma control: create shapes, text, components, set styles, auto-layout, variables, export. 80+ tools.
автор: dannoteLogo.dev
Search and retrieve company logos by brand or domain. Customize size, format, and theme to match your design needs. Accelerate design, prototyping, and content
автор: NOVA-3951PIX4Dmatic
Enables GUI automation for controlling PIX4Dmatic on Windows through MCP. Supports launching, focusing, capturing screenshots, sending hotkeys, clicking UI elem
автор: jangjo123Compare Selvans with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории design
