feat: add MCP tools, refined recipe steps for schema extension verification and update Docker requirements
- Add mcp/operations/importHosts.graphql for flexible, name-based host provisioning.
- Split schema verification operations into createVerificationHost.graphql and verifySchemaExtension.graphql to support Apollo MCP server requirements.
- Improve mcp/operations/createHost.graphql with better type mapping and error message retrieval.
- Fix syntax error in importHosts.graphql by replacing unsupported triple-quote docstrings with standard comments.
- Add src/test/mcp_operations_validation.test.ts to automatically validate MCP operations against the GraphQL schema.
- Update docs/howtos/cookbook.md with 🤖 AI/MCP guidance and refined recipe steps for schema extension verification.
- Update README.md, docs/howtos/mcp.md, and .junie/guidelines.md to:
- Add Docker (v27+) and Docker Compose (v2.29+) version requirements to the Tech Stack.
- Enforce the use of docker compose (without hyphen) for all commands in the Environment guidelines.
- Replace legacy docker-compose references across all documentation with the new command format.
This commit is contained in:
parent
a9940063e9
commit
9a79fc8e4c
9 changed files with 92 additions and 13 deletions
|
|
@ -7,7 +7,7 @@ The [Roadmap](../roadmap.md) is to be considered as outlook giving constraints o
|
|||
|
||||
### Environment
|
||||
- **Operating System**: Windows with WSL + Ubuntu installed.
|
||||
- **Commands**: Always execute Linux commands (e.g. use `ls` instead of `dir`).
|
||||
- **Commands**: Always execute Linux commands (e.g. use `ls` instead of `dir`) and use `docker compose` (without hyphen) instead of `docker-compose`.
|
||||
|
||||
|
||||
## Tech Stack
|
||||
|
|
@ -15,7 +15,7 @@ The [Roadmap](../roadmap.md) is to be considered as outlook giving constraints o
|
|||
- **Language**: TypeScript (ESM)
|
||||
- **API**: GraphQL (Apollo Server 4)
|
||||
- **Testing**: Jest
|
||||
- **Deployment**: Docker
|
||||
- **Deployment**: Docker (v27+) and Docker Compose (v2.29+)
|
||||
|
||||
## Project Structure
|
||||
- `src/api/`: GraphQL server configuration, schema loading, and root resolvers (see `createResolvers` in `resolvers.ts`).
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ The Zabbix GraphQL API acts as a wrapper and enhancer for the native Zabbix JSON
|
|||
- *Reference*: `codegen.ts`, `src/schema/generated/graphql.ts`, `tsconfig.json`, `package.json` (devDependencies for GraphQL Codegen)
|
||||
|
||||
- **AI Agent & MCP Enablement**: Native support for Model Context Protocol (MCP) and AI-driven automation. GraphQL's strongly-typed, introspectable nature provides a superior interface for AI agents compared to traditional REST APIs.
|
||||
- *Reference*: `docs/howtos/mcp.md`, `.ai/mcp/mcp.json` (Sample Config), `mcp-config.yaml`, `docker-compose.yml` (MCP service)
|
||||
- *Reference*: `docs/howtos/mcp.md`, `.ai/mcp/mcp.json` (Sample Config), `mcp-config.yaml`, `docker compose` (MCP service)
|
||||
|
||||
> **Planned features**: For an overview of achieved milestones and planned enhancements have a look at the [**Roadmap**](./roadmap.md).
|
||||
|
||||
|
|
@ -50,6 +50,7 @@ See the [How-To Overview](./docs/howtos/README.md) for a complete list of docume
|
|||
Before you begin, ensure you have met the following requirements:
|
||||
|
||||
- **Node.js**: Version 24 (LTS) or higher recommended.
|
||||
- **Docker**: Version 27 or higher and **Docker Compose** v2.29 or higher (use `docker compose` instead of `docker-compose`).
|
||||
- **Zabbix**: A running Zabbix instance (compatible with Zabbix 6.0+) with API access.
|
||||
- **Zabbix Super Admin Token** (for full functionality / privilege escalation).
|
||||
- **Zabbix User Access** (groups and roles depending on your use case).
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ type DistanceTrackerValues {
|
|||
timeFrom: Time
|
||||
timeUntil: Time
|
||||
count: Int
|
||||
# The distances are modelled using a type which is already defined in location_tracker_commons.graphql
|
||||
distances: [SensorDistanceValue!]
|
||||
}
|
||||
```
|
||||
|
|
@ -57,7 +58,7 @@ type DistanceTrackerValues {
|
|||
### ⚙️ Step 2: Configure Environment Variables
|
||||
Add the new schema and resolver to your `.env` file:
|
||||
```env
|
||||
ADDITIONAL_SCHEMAS=./schema/extensions/distance_tracker.graphql
|
||||
ADDITIONAL_SCHEMAS=./schema/extensions/distance_tracker.graphql,./schema/extensions/location_tracker_commons.graphql
|
||||
ADDITIONAL_RESOLVERS=DistanceTrackerDevice
|
||||
```
|
||||
Restart the API server.
|
||||
|
|
@ -66,12 +67,12 @@ Restart the API server.
|
|||
|
||||
#### Method A: Manual Creation in Zabbix
|
||||
If you prefer to configure Zabbix manually:
|
||||
1. **Create Template**: Create a template named `Distance Tracker Device`.
|
||||
2. **Create Items**: Add items with keys that match the GraphQL fields:
|
||||
1. **Create Template**: Create a template named `DISTANCE_TRACKER`.
|
||||
2. **Create Items**: Add items with keys that match the GraphQL fields (using hierarchical mapping):
|
||||
* `state.current.timeFrom`
|
||||
* `state.current.timeUntil`
|
||||
* `state.current.count`
|
||||
* `state.current.json_distances` (maps to `distances` array)
|
||||
* `state.current.json_distances` (maps to `distances` array via `json_` prefix)
|
||||
3. **Add Tag**: Add a host tag to the template with name `deviceType` and value `DistanceTrackerDevice`.
|
||||
|
||||
#### Method B: Automated Import
|
||||
|
|
@ -82,7 +83,8 @@ Execute the `importTemplates` mutation to create the template and items automati
|
|||
Verify that the new type is available and correctly mapped by creating a test host and querying it.
|
||||
|
||||
#### 1. Create a Test Host
|
||||
Use the `importHosts` mutation to create a host and explicitly set its `deviceType` to `DistanceTrackerDevice`.
|
||||
Use the `importHosts` mutation (or `createHost` if IDs are already known) to create a host and explicitly set its `deviceType` to `DistanceTrackerDevice`.
|
||||
|
||||
```graphql
|
||||
mutation CreateTestDistanceTracker($host: String!, $groupNames: [String!]!) {
|
||||
importHosts(hosts: [{
|
||||
|
|
@ -97,7 +99,8 @@ mutation CreateTestDistanceTracker($host: String!, $groupNames: [String!]!) {
|
|||
```
|
||||
|
||||
#### 2. Query the Device
|
||||
Query the newly created device. Use the `tag_deviceType: ["DistanceTrackerDevice"]` argument to ensure you only retrieve devices of this specific type and prevent showing all devices.
|
||||
Query the newly created device. Use the `tag_deviceType: ["DistanceTrackerDevice"]` argument to ensure you only retrieve devices of this specific type and prevent showing all devices of any type.
|
||||
|
||||
```graphql
|
||||
query VerifyNewDeviceType {
|
||||
# 1. Check if the type exists in the schema
|
||||
|
|
@ -126,6 +129,11 @@ query VerifyNewDeviceType {
|
|||
|
||||
> **Reference**: See how items map to fields in the [Zabbix to GraphQL Mapping](../../README.md#zabbix-to-graphql-mapping).
|
||||
|
||||
### 🤖 AI/MCP
|
||||
AI agents can use the generalized `verifySchemaExtension.graphql` operations to automate this step:
|
||||
- **CreateVerificationHost**: Automatically imports a test host with the correct `deviceType`.
|
||||
- **VerifySchemaExtension**: Queries the newly created device to verify it is correctly mapped to the new type.
|
||||
|
||||
---
|
||||
|
||||
## 🍳 Recipe: Provisioning a New Host
|
||||
|
|
@ -140,6 +148,9 @@ Define the host name, groups, and templates to link.
|
|||
### 🚀 Step 2: Execute `createHost` Mutation
|
||||
For more details on the input fields, see the [Reference: createHost](../../schema/mutations.graphql).
|
||||
|
||||
### 🤖 AI/MCP
|
||||
AI agents should prefer using the `importHosts` MCP tool for provisioning as it allows using names for host groups instead of IDs.
|
||||
|
||||
```graphql
|
||||
mutation CreateNewHost($host: String!, $groups: [Int!]!, $templates: [Int!]!) {
|
||||
createHost(host: $host, hostgroupids: $groups, templateids: $templates) {
|
||||
|
|
@ -303,7 +314,7 @@ Confirm that the agent can successfully interact with the API:
|
|||
- The agent should use the `apiVersion` query and respond with the version number.
|
||||
|
||||
### 💡 Alternative: Using Pre-running MCP Server
|
||||
If you already have the MCP server running locally (e.g. via `docker-compose.yml`), you can use a simpler configuration.
|
||||
If you already have the MCP server running locally (e.g. via `docker compose`), you can use a simpler configuration.
|
||||
- **Sample Configuration**: See [.ai/mcp/mcp.json](../../.ai/mcp/mcp.json) for a sample that connects to a running MCP server via HTTP.
|
||||
- **Usage**: Use this `url`-based configuration in your Claude Desktop or IDE settings instead of the `command`-based setup if you prefer to manage the MCP server lifecycle separately.
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ You can start both the Zabbix GraphQL API and the Apollo MCP Server using Docker
|
|||
```
|
||||
- **Start Services**:
|
||||
```bash
|
||||
docker-compose up -d
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
This will:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
mutation CreateHost($host: String!, $hostgroupids: [Int!]!, $templateids: [Int!]) {
|
||||
mutation CreateHost($host: String!, $hostgroupids: [Int!]!, $templateids: [Int!]!) {
|
||||
createHost(host: $host, hostgroupids: $hostgroupids, templateids: $templateids) {
|
||||
hostids
|
||||
error
|
||||
error {
|
||||
message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
13
mcp/operations/createVerificationHost.graphql
Normal file
13
mcp/operations/createVerificationHost.graphql
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
mutation CreateVerificationHost($deviceKey: String!, $deviceType: String!, $groupNames: [String!]!) {
|
||||
importHosts(hosts: [{
|
||||
deviceKey: $deviceKey,
|
||||
deviceType: $deviceType,
|
||||
groupNames: $groupNames
|
||||
}]) {
|
||||
hostid
|
||||
message
|
||||
error {
|
||||
message
|
||||
}
|
||||
}
|
||||
}
|
||||
11
mcp/operations/importHosts.graphql
Normal file
11
mcp/operations/importHosts.graphql
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Import multiple hosts/devices into Zabbix.
|
||||
# This is a powerful tool for bulk provisioning of hosts using their names and types.
|
||||
mutation ImportHosts($hosts: [CreateHost!]!) {
|
||||
importHosts(hosts: $hosts) {
|
||||
hostid
|
||||
message
|
||||
error {
|
||||
message
|
||||
}
|
||||
}
|
||||
}
|
||||
13
mcp/operations/verifySchemaExtension.graphql
Normal file
13
mcp/operations/verifySchemaExtension.graphql
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
query VerifySchemaExtension($typeName: String!, $deviceKey: String) {
|
||||
allDevices(tag_deviceType: [$typeName], filter_host: $deviceKey) {
|
||||
hostid
|
||||
host
|
||||
name
|
||||
deviceType
|
||||
state {
|
||||
operational {
|
||||
timestamp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/test/mcp_operations_validation.test.ts
Normal file
28
src/test/mcp_operations_validation.test.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import {schema_loader} from "../api/schema.js";
|
||||
import {readdirSync, readFileSync} from "node:fs";
|
||||
import {parse, validate} from "graphql";
|
||||
import path from "node:path";
|
||||
|
||||
describe("MCP Operations Validation", () => {
|
||||
let schema: any;
|
||||
|
||||
beforeAll(async () => {
|
||||
schema = await schema_loader();
|
||||
});
|
||||
|
||||
const operationsDir = "./mcp/operations";
|
||||
const files = readdirSync(operationsDir).filter(f => f.endsWith(".graphql"));
|
||||
|
||||
test.each(files)("Operation file %s should be valid against schema", (file) => {
|
||||
const filePath = path.join(operationsDir, file);
|
||||
const content = readFileSync(filePath, "utf-8");
|
||||
const document = parse(content);
|
||||
const errors = validate(schema, document);
|
||||
|
||||
if (errors.length > 0) {
|
||||
console.error(`Validation errors in ${file}:`, errors.map(e => e.message));
|
||||
}
|
||||
|
||||
expect(errors).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue