Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions docs/mcp_server/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# SC4S MCP Server

The **SC4S MCP Server** is a [Model Context Protocol](https://modelcontextprotocol.io) server
that exposes Splunk Connect for Syslog (SC4S) knowledge and a safe management
API to any MCP-compatible AI assistant or agent (for example, Cursor,
Claude Desktop, or Visual Studio Code with an MCP extension). It lets the
assistant help you discover supported vendors, author and validate
syslog-ng parsers, inspect a running SC4S instance, and apply
configuration changes through well-defined MCP tools, resources, and
prompts.

## What it is

The server is shipped as a small containerized Python application based on
[FastMCP](https://github.com/jlowin/fastmcp). It provides three categories of
capabilities:

| Category | Purpose |
|---|----------------------------------------------------------------------------------------------------------------------------------|
| **Tools** | Callable functions the assistant can invoke (for example: upload a new parser, modify environment variables, check SC4S health). |
| **Resources** | Read-only documents the assistant can load on demand (parser creation guide, troubleshooting guide, vendor docs). |
| **Prompts** | Guided workflows (for example: `create_parser`, `troubleshoot_sc4s`) that orient the assistant to a specific task. |

The full list of tools, resources, and prompts is documented in
[Tools](tools.md) and [Resources and prompts](resources_and_prompts.md).

## Architecture

The MCP server runs in its own OCI container (Docker or Podman) and
communicates with:

1. Your **MCP client** (the AI assistant or agent) over `stdio` on the
local machine, or over `SSE` (HTTP) when the client is remote.
2. The **SC4S container's management API**, an HTTP REST API exposed by
the SC4S container (default port `8080`) that handles configuration
reads and writes for `env_file`, custom parsers, and Splunk metadata.

![MCP-server-diagram.svg](../resources/images/MCP-server-diagram.svg)

## Security model

!!! important "The MCP server never runs commands outside its container"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think important is still rendering as note maybe we can render !!!warning instead as it would look more like something that needs to be read?

Copy link
Copy Markdown
Collaborator Author

@Kawron Kawron May 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, you are right, it renders as a note. But on the other hand I don't think warning is better option. The fact that it doesn't runs any commands is a good thing, but "!" and orange border would indicate that this is sth bad

The SC4S MCP server does **not** execute shell commands, scripts, or
binaries on your host. It does **not** invoke `docker`, `podman`,
`systemctl`, `syslog-ng`, `bash`, or any other process outside the
container in which it runs.

All management actions are performed by calling a well-defined HTTP
REST API exposed by the SC4S container itself. That API, and only
that API, decides what configuration is accepted, validates syntax,
and restarts `syslog-ng` inside the SC4S container when needed.

Concretely, the MCP server only does two kinds of I/O:

* **Reads** a small, read-only set of files that are baked into its own
container image at build time: the documentation under `docs/`, the
parser library under `package/lite/etc/addons/`, and the parser-creator
knowledge base. These are static; the MCP server does not reach into
your host filesystem.
* **Makes HTTP(S) requests** to `SC4S_API_URL`, the REST API running
inside the SC4S container. Every "management" tool is a thin wrapper
over a single HTTP call. There is no shell, no `exec`, and no process
spawning.

Additional the shipped image:

* Runs as a non-root user (`uid 10001`), as declared in the Dockerfile
(`USER mcp`).
* Does not mount or connect to the Docker or Podman socket; the MCP
server has no container-management capabilities.
* The MCP server container itself does not require any host-filesystem
bind mounts. (The `env_file` bind mount described in
[Installation](installation.md#prepare-your-sc4s-instance) is applied
to the SC4S container, not to the MCP server container.)

## Next steps

* **[Installation](installation.md)**, build the image, run it with
Docker or Podman, and configure your MCP client.
* **[Tools](tools.md)**, reference of every callable tool.
* **[Resources and prompts](resources_and_prompts.md)**, reference of
the available MCP resources and guided prompts.
186 changes: 186 additions & 0 deletions docs/mcp_server/installation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
# Installing the SC4S MCP Server

The SC4S MCP server is distributed as a container image. It can be run on
your local workstation for use with a local AI assistant (using the
`stdio` transport), or on a shared host, such as the same machine as your
SC4S instance, where remote assistants and agents connect to it over the
`SSE` transport.

!!! note "No host commands are executed"
Regardless of how you run the container, the MCP server itself never
runs commands outside the container. See
[Security model](index.md#security-model-no-host-command-execution).

## Prerequisites

Comment thread
Kawron marked this conversation as resolved.
SC4S MCP server is currently available only for Podman or Docker runtimes.

* A running SC4S instance exposing the management REST API (default port
`8080`).
* Docker or Podman on the host where the MCP server will run.
* An MCP-compatible AI assistant or agent that can connect to the server
over `stdio` or `SSE` (for example, Cursor, Claude Desktop, or Visual
Studio Code with an MCP extension).

## Configuration reference

The MCP server is configured through environment variables.

| Variable | Default | Description |
|---|---|---|
| `MCP_TRANSPORT` | `stdio` | Transport mode: `stdio` for local clients, `sse` for remote clients. |
| `MCP_HOST` | `0.0.0.0` | Bind address used in `sse` mode. |
| `MCP_PORT` | `8000` | TCP port used in `sse` mode. |
| `SC4S_API_URL` | `http://localhost:8080` | URL of the SC4S management REST API. The MCP server calls this URL for all management tools. |

## Build the image

The Dockerfile is part of the SC4S repository. Build from the repository
root so that the `docs/`, `package/lite/etc/addons/`, and
`.agents/skills/parser-creator/` directories are available to the build
context.

Docker:

```bash
docker build -t sc4s-mcp -f sc4s_mcp/Dockerfile .
```

Podman:

```bash
podman build -t sc4s-mcp -f sc4s_mcp/Dockerfile .
```
Comment on lines +36 to +53
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd write the steps based on the fact that we would probably be relesing that as build container in the future, instad of the instruction to clone and build it

Copy link
Copy Markdown
Collaborator Author

@Kawron Kawron May 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, but maybe until it's released let's keep it that way. Maybe it can be useful for developers


## Run the container

The examples below assume the SC4S container is reachable at
`http://<SC4S_HOST>:8080`. If SC4S runs on the same host, use
`--network host` and point `SC4S_API_URL` to `http://127.0.0.1:8080`.

Docker:

```bash
docker run -d \
-p 8000:8000 \
-e SC4S_API_URL=http://<SC4S_HOST>:8080 \
--name sc4s-mcp \
sc4s-mcp
```

Same host as SC4S (Linux):

```bash
docker run -d --network host \
-e SC4S_API_URL=http://127.0.0.1:8080 \
--name sc4s-mcp \
sc4s-mcp
```

Podman (locally built images are stored under the `localhost/` prefix):

```bash
podman run -d \
-p 8000:8000 \
-e SC4S_API_URL=http://<SC4S_HOST>:8080 \
--name sc4s-mcp \
localhost/sc4s-mcp
```

Same host as SC4S (Linux):

```bash
podman run -d --network host \
-e SC4S_API_URL=http://127.0.0.1:8080 \
--name sc4s-mcp \
localhost/sc4s-mcp
```

The image ships a healthcheck that verifies the SSE endpoint is up. Check
the container status with:

```bash
docker ps # or: podman ps
```

## Prepare your SC4S instance

The MCP management tools (`sc4s_set_env`, `sc4s_add_parser`, and others)
need to read and write SC4S's `env_file` at runtime. The `--env-file`
Docker/Podman flag alone is **not sufficient**: it injects variables at
startup but does not make the file visible inside the container.

Bind-mount the file in addition to passing `--env-file`:

```
-v /opt/sc4s/env_file:/opt/sc4s/env_file:z
```

### systemd unit example

If you run SC4S via systemd, add the mount variable:

```ini
Environment="SC4S_ENV_FILE_MOUNT=/opt/sc4s/env_file:/opt/sc4s/env_file:z"
```

and include `-v "$SC4S_ENV_FILE_MOUNT"` in your `ExecStart` alongside the
other `-v` flags:

```ini
ExecStart=/usr/bin/podman run \
-e "SC4S_CONTAINER_HOST=${SC4SHOST}" \
-v "$SC4S_PERSIST_MOUNT" \
-v "$SC4S_LOCAL_MOUNT" \
-v "$SC4S_ARCHIVE_MOUNT" \
-v "$SC4S_TLS_MOUNT" \
-v "$SC4S_ENV_FILE_MOUNT" \
--env-file=/opt/sc4s/env_file \
--network host \
--name SC4S \
--rm $SC4S_IMAGE
```

Then reload and restart:

```bash
sudo systemctl daemon-reload
sudo systemctl restart sc4s
```

### Generic MCP client configuration

Most MCP clients accept one of two connection styles. Consult your
client's documentation for the exact configuration file and its location;
the shape of the configuration is typically the same across clients.

**Local process (stdio)**: the client launches the server as a child
process and communicates via standard input/output. Provide:

* a `command` to execute (for example `docker` or `podman`),
* an `args` array that starts the MCP server,
* optional environment variables (`SC4S_API_URL`, `MCP_TRANSPORT=stdio`).

**Remote endpoint (SSE)**: the client connects to an HTTP URL exposing
the MCP SSE endpoint. Provide:

* a `url` pointing at `http://<MCP_HOST>:8000/sse`,
* any additional headers required by your deployment (for example, a
reverse-proxy auth header).

## Verify the installation

1. Confirm the container is running: `docker ps` or `podman ps`.
2. Confirm the MCP client sees the server. Most clients list available
MCP servers in a dedicated panel or on startup.
3. From the assistant, call the `sc4s_health` tool. A healthy instance
returns a status payload from the SC4S management API. An error like
`"SC4S instance unreachable at http://..."` means the MCP server
could reach out but SC4S is not answering. Check `SC4S_API_URL`, the
SC4S container status, and network connectivity.

## Upgrading

To upgrade the MCP server, rebuild the image from a newer revision of
the repository and restart the container. Configuration is
environment-based, so no data migration is required.
95 changes: 95 additions & 0 deletions docs/mcp_server/resources_and_prompts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Resources and prompts

In addition to [tools](tools.md), the SC4S MCP server exposes two other
MCP primitives:

* **Resources**: read-only documents that the assistant (or the user)
can request by URI. Resources are static content baked into the MCP
container image; they do not touch SC4S or the host.
* **Prompts**: pre-built workflows that seed a conversation with all
the context needed for a specific task. Prompts do not execute code
on their own; they just structure the conversation.

## Resources

All resources use the `sc4s://` URI scheme. They are assembled from the
project's markdown documentation at the time they are fetched, so they
always match the docs that ship with the image you are running.

| URI | Contents |
|---|---|
| `sc4s://docs/creating_parsers` | The full parser-creation guide: the `index.md`, `filter_message.md`, `parse_message.md`, and `unit_tests.md` chapters, concatenated. Use this to give the assistant the conventions it needs to write a correct parser. |
| `sc4s://docs/troubleshooting` | The troubleshooting guide: startup/validation checks, logging resources, PCAP replay, and Splunk health checks, concatenated. Use this when diagnosing a problem. |
| `sc4s://docs/vendor/{vendor}` | All markdown documentation for a given vendor under `docs/sources/vendor/{vendor}/`. Replace `{vendor}` with a directory name; the list is available from the `list_vendors` tool. |

Resources are read-only by construction: they return text, nothing
else. The server cannot use them to modify state.

## Prompts

Prompts are ready-made workflows that include the relevant knowledge
base and a set of diagnostic steps. Invoke them from your client's
prompt picker, most mcp clients should expose such menu.

### `create_parser`

Guided workflow for authoring a new SC4S syslog-ng parser from sample
logs. The prompt loads the project's parser-creation knowledge base and
asks the assistant to follow those conventions exactly.

**Parameters**

| Name | Description |
|---|---|
| `vendor` | Vendor name (free text, for example `cisco`). |
| `product` | Product name (free text, for example `asa`). |
| `sample_logs` | One or more raw log lines to base the parser on. |

**Typical flow after invocation**

1. The assistant reads the knowledge base and the sample logs.
2. It calls `list_vendor_parsers` / `get_parser` to learn existing
conventions for the same vendor (if any).
3. It drafts a new `.conf` parser and the corresponding unit tests.
4. With your approval, it uploads the parser via `sc4s_add_parser`.

### `troubleshoot_sc4s`

Guided workflow for diagnosing a live SC4S issue. The prompt loads the
troubleshooting docs and asks the assistant to run the standard
diagnostic sequence before making any changes.

**Parameters**

| Name | Description |
|---|---|
| `symptom` | Free-text description of what you are seeing (for example, *"no Cisco ASA events in Splunk"*). |

**Diagnostic steps seeded by the prompt**

1. Call `sc4s_health` to check the instance status.
2. Call `sc4s_get_env` to review the current configuration.
3. Call `sc4s_list_custom_parsers` to list deployed custom parsers.
4. Propose specific fixes.
5. Apply configuration changes via `sc4s_set_env` only after explaining
the reasoning.

## Combining tools, resources, and prompts

A typical interaction uses all three primitives together. For example,
adding support for a new vendor might look like this:

1. Invoke the `create_parser` prompt with vendor, product, and sample
logs.
2. The assistant pulls context from `sc4s://docs/creating_parsers` and
calls read-only tools (`list_vendors`, `list_vendor_parsers`,
`get_parser`) to inspect existing work.
3. After you review the draft, the assistant calls `sc4s_add_parser`
to deploy it.
4. If the SC4S management API rejects the parser, the change is rolled
back automatically and the assistant iterates.

Throughout this flow the MCP server itself only reads files from its own
container and makes HTTP calls to `SC4S_API_URL`. See
[Security model](index.md#security-model-no-host-command-execution) for
details.
Loading
Loading