data.gv.at MCP Server Logodata.gv.at MCP

Other MCP Clients

Use data.gv.at MCP Server with other MCP-compatible clients

data.gv.at MCP Server works with any MCP 1.0-compatible client. This guide shows configuration for Continue (VS Code), Cline (terminal), and FastMCP client libraries.

Supported clients

  • Claude Desktop - Anthropic's official client (Setup guide)
  • Continue - VS Code extension for AI coding assistance
  • Cline - Terminal-based MCP client
  • FastMCP Client - Python library for custom integrations
  • Custom clients - Any client implementing MCP 1.0 specification

Continue (VS Code extension)

Continue brings AI assistance into VS Code through an extension.

Installation

  1. Open VS Code Extensions (Ctrl+Shift+X or Cmd+Shift+X)
  2. Search for "Continue"
  3. Click Install
  4. Open Continue settings panel

Configuration

Add data.gv.at MCP Server to Continue's config file (.continue/config.json):

{
  "mcpServers": {
    "austria-data": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "/absolute/path/to/datagvat-mcp/mcp",
        "python",
        "-m",
        "app.server"
      ],
      "transport": "stdio"
    }
  }
}

Replace /absolute/path/to/datagvat-mcp/mcp with your installation path.

Usage

In VS Code with Continue active, prefix queries with the server name:

@austria-data search for population datasets in Vienna

The @austria-data prefix tells Continue which MCP server to use.

Cline (terminal client)

Cline provides MCP access from the command line.

Installation

npm install -g @modelcontextprotocol/cline

Configuration

Create configuration file at ~/.cline/config.json:

{
  "servers": {
    "austria-data": {
      "command": "python",
      "args": ["-m", "app.server"],
      "cwd": "/absolute/path/to/datagvat-mcp/mcp",
      "env": {
        "AUSTRIA_MCP_LOG_LEVEL": "INFO"
      }
    }
  }
}

Replace /absolute/path/to/datagvat-mcp/mcp with your installation path.

Usage

Connect to the server and call tools:

cline connect austria-data
> list_catalogues(limit=5)

FastMCP client library

FastMCP provides Python client libraries for in-memory, subprocess, and HTTP connections. Use these libraries to build custom integrations without implementing the MCP protocol yourself.

Installation

pip install fastmcp>=2.14.0

In-memory client pattern

Connect directly to the server without subprocess overhead. Best for testing and embedded usage.

from fastmcp import FastMCP
from fastmcp.client import Client

# Import server instance
from app.server import mcp

async def use_austria_mcp():
    """Direct in-memory connection to server."""
    async with Client(mcp) as client:
        # List available tools
        tools = await client.list_tools()
        print(f"Available tools: {[t.name for t in tools]}")

        # Call tool with arguments
        result = await client.call_tool(
            "search_datasets",
            arguments={"query": "population", "limit": 10}
        )

        print(result)

        # Access resources
        resources = await client.list_resources()
        dataset = await client.read_resource("piveau://dataset/bev-stat-wien-2024")

When to use in-memory client:

  • Unit testing MCP tools
  • Jupyter notebooks and data science workflows
  • Embedded applications (desktop apps, CLI tools)
  • Development and debugging

Benefits:

  • No subprocess management required
  • No stdio parsing overhead
  • Type-safe tool calls with Pydantic validation
  • 10-100x faster than subprocess (no IPC overhead)
  • Full stack traces for debugging

Subprocess client pattern

Run the server in a separate process with full isolation. Recommended for production.

from fastmcp.client import SubprocessClient

async def use_austria_mcp_isolated():
    """Production pattern with process isolation."""
    client = SubprocessClient(
        command="uv",
        args=["run", "--directory", "/path/to/mcp", "python", "-m", "app.server"],
        env={
            "AUSTRIA_MCP_LOG_LEVEL": "INFO",
            "AUSTRIA_MCP_REQUEST_TIMEOUT": "60"
        }
    )

    async with client:
        # Same API as in-memory client
        tools = await client.list_tools()

        result = await client.call_tool(
            "list_catalogues",
            arguments={"limit": 5}
        )

        print(result)

When to use subprocess client:

  • Production deployments
  • Long-running services
  • Untrusted code isolation
  • Cross-platform compatibility

Benefits:

  • Server crashes don't affect client
  • OS-level resource limits (memory, CPU)
  • Client and server can use different Python versions
  • Standard MCP protocol over stdio

HTTP client pattern (SSE)

Access the server remotely over HTTP using Server-Sent Events. Enables web applications and distributed systems.

Start the SSE server:

# Development server with hot reload
fastmcp dev app.server:mcp --host 0.0.0.0 --port 8080

# Production server with uvicorn
uvicorn app.sse_server:app --host 0.0.0.0 --port 8080 --workers 4

Connect from client:

from fastmcp.client import HTTPClient

async def use_austria_mcp_remote():
    """Web-based client using Server-Sent Events."""
    client = HTTPClient(url="http://localhost:8080/sse")

    async with client:
        result = await client.call_tool(
            "semantic_search_datasets",
            arguments={"natural_query": "health data from Vienna"}
        )

        print(result)

When to use HTTP client:

  • Web applications (JavaScript/TypeScript frontends)
  • Distributed systems with remote servers
  • Multi-tenant deployments
  • Browser-based tools

Benefits:

  • Remote access across network
  • Multiple clients connect to one server
  • Load balancing with reverse proxies
  • Web browser support via EventSource API

Error handling

Handle errors with try-except blocks:

from fastmcp.client import Client
from fastmcp.exceptions import ToolError, ConnectionError, TimeoutError

async def robust_client():
    try:
        async with Client(mcp) as client:
            result = await client.call_tool(
                "search_datasets",
                arguments={"query": "population"}
            )
    except ToolError as e:
        # Tool execution failed (invalid parameters, API error)
        print(f"Tool error: {e.message}")
    except ConnectionError as e:
        # Cannot connect to server
        print(f"Connection error: {e}")
    except TimeoutError as e:
        # Request exceeded timeout
        print(f"Timeout: {e}")

Error types:

  • ToolError - Invalid parameters or API failures
  • ConnectionError - Server not reachable
  • TimeoutError - Request exceeded deadline
  • ValidationError - Client-side validation failed

Progress tracking

Monitor long-running operations with progress callbacks:

from fastmcp.client import Client

async def track_progress():
    async with Client(mcp) as client:
        # Define progress callback
        def on_progress(current: int, total: int, message: str):
            percent = (current / total) * 100
            print(f"[{percent:.0f}%] {message}")

        client.on_progress = on_progress

        # Call tool with progress updates
        result = await client.call_tool(
            "analyze_dataset_quality",
            arguments={"dataset_id": "bev-stat-wien-2024"}
        )

Output:

[0%] Fetching dataset metadata...
[25%] Analyzing completeness...
[50%] Checking data accessibility...
[75%] Computing quality score...
[100%] Analysis complete

Batch operations

Execute multiple tool calls in parallel:

import asyncio
from fastmcp.client import Client

async def batch_search():
    async with Client(mcp) as client:
        # Parallel tool calls using asyncio.gather
        results = await asyncio.gather(
            client.call_tool("search_datasets", {"query": "health"}),
            client.call_tool("search_datasets", {"query": "education"}),
            client.call_tool("search_datasets", {"query": "transport"}),
        )

        for query, result in zip(["health", "education", "transport"], results):
            print(f"{query}: {result['count']} datasets")

Testing with FastMCP client

FastMCP client simplifies unit testing:

import pytest
from fastmcp.client import Client
from app.server import mcp

@pytest.mark.asyncio
async def test_search_datasets():
    """Test dataset search functionality."""
    async with Client(mcp) as client:
        # Test basic search
        result = await client.call_tool(
            "search_datasets",
            arguments={"query": "population", "limit": 10}
        )

        assert result["count"] > 0
        assert len(result["results"]) <= 10
        assert all("title" in r for r in result["results"])

@pytest.mark.asyncio
async def test_tool_validation():
    """Test parameter validation."""
    async with Client(mcp) as client:
        # Invalid limit should raise ValidationError
        with pytest.raises(Exception) as exc_info:
            await client.call_tool(
                "search_datasets",
                arguments={"limit": -1}  # Invalid
            )

        assert "validation" in str(exc_info.value).lower()

Client configuration

Configure timeout, environment, and logging:

from fastmcp.client import SubprocessClient

client = SubprocessClient(
    command="python",
    args=["-m", "app.server"],
    cwd="/path/to/mcp",
    timeout=60.0,  # Request timeout in seconds
    env={
        "AUSTRIA_MCP_LOG_LEVEL": "DEBUG",
        "AUSTRIA_MCP_REQUEST_TIMEOUT": "30",
    },
    capture_stderr=True,  # Capture server logs
)

async with client:
    # Access server logs
    if client.stderr:
        logs = await client.stderr.read()
        print(logs)

Custom client implementation

For advanced use cases, extend BaseClient:

from fastmcp.client.base import BaseClient
from fastmcp.protocol import RequestMessage, ResponseMessage

class CustomClient(BaseClient):
    """Custom client with specialized features."""

    async def connect(self):
        """Establish connection to server."""
        # Your connection logic
        pass

    async def send_message(self, message: RequestMessage) -> ResponseMessage:
        """Send message and receive response."""
        # Your message handling
        pass

    async def close(self):
        """Close connection."""
        pass

See the FastMCP documentation for detailed patterns and middleware development.

Custom MCP client implementation

Build your own MCP client by implementing the protocol directly.

MCP protocol requirements

Your client must implement:

  1. stdio transport - Communicate via stdin/stdout
  2. JSON-RPC 2.0 - Message format
  3. MCP 1.0 messages - Initialize, tools/call, resources/list, etc.

Connection flow

import subprocess
import json

# 1. Start server process
process = subprocess.Popen(
    ["python", "-m", "app.server"],
    cwd="/path/to/mcp",
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    text=True
)

# 2. Send initialize request
initialize_request = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
        "protocolVersion": "1.0",
        "clientInfo": {
            "name": "my-client",
            "version": "1.0.0"
        }
    }
}

process.stdin.write(json.dumps(initialize_request) + "\n")
process.stdin.flush()

# 3. Read initialize response
response = json.loads(process.stdout.readline())

# 4. Send tools/call request
tool_request = {
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
        "name": "list_catalogues",
        "arguments": {"limit": 5}
    }
}

process.stdin.write(json.dumps(tool_request) + "\n")
process.stdin.flush()

# 5. Read tool response
result = json.loads(process.stdout.readline())
print(result["result"])

Environment-specific configuration

Development environment

Use debug logging and dev mode:

{
  "mcpServers": {
    "austria-data-dev": {
      "command": "python",
      "args": ["-m", "app.server"],
      "cwd": "/path/to/dev/mcp",
      "env": {
        "AUSTRIA_MCP_LOG_LEVEL": "DEBUG",
        "AUSTRIA_MCP_DEV_MODE": "true"
      }
    }
  }
}

Production environment

Optimize for production with reduced logging:

{
  "mcpServers": {
    "austria-data-prod": {
      "command": "python",
      "args": ["-m", "app.server"],
      "cwd": "/path/to/prod/mcp",
      "env": {
        "AUSTRIA_MCP_LOG_LEVEL": "WARNING",
        "AUSTRIA_MCP_LOG_FORMAT": "json",
        "AUSTRIA_MCP_REQUEST_TIMEOUT": "60"
      }
    }
  }
}

Transport options

stdio (default)

Default transport using standard input/output:

{
  "command": "python",
  "args": ["-m", "app.server"],
  "transport": "stdio"
}

Pros:

  • Simple and widely supported
  • No network configuration needed
  • Works across all platforms

Cons:

  • Single process communication only
  • No remote access

SSE (Server-Sent Events)

For web-based or remote clients:

# Start server with SSE transport
uvicorn app.sse_server:app --host 0.0.0.0 --port 8080

Client configuration:

{
  "transport": "sse",
  "url": "http://localhost:8080/sse"
}

Pros:

  • Supports remote clients
  • Multiple concurrent connections
  • Web browser compatibility

Cons:

  • Requires network setup
  • Additional security considerations (HTTPS, authentication)

Troubleshooting

Client can't find server

Symptom: Connection timeout or "command not found"

Fix:

  • Use absolute paths in configuration
  • Verify Python is in PATH with which python (macOS/Linux) or where python (Windows)
  • Check working directory points to mcp/ folder

Tools not visible

Symptom: Client connects but shows no tools

Fix:

  • Ensure initialize handshake completed successfully
  • Check client implements tools/list method
  • Verify MCP protocol version compatibility (client and server must both use MCP 1.0)

Performance issues

Symptom: Slow responses or timeouts

Fix:

  • Increase request timeout in client config
  • Check network latency if using SSE transport
  • Monitor server logs for bottlenecks
  • Use in-memory client pattern for local testing (eliminates IPC overhead)

Next steps

How is this guide?

Last updated on

On this page