TMSMCPTransport
Overview
The TMS MCP (Model Context Protocol) Transport framework provides a unified interface for various communication transport mechanisms. Built around the abstract base class TTMSMCPTransport, this framework enables developers to implement different communication protocols while maintaining a consistent API.
The framework includes three concrete implementations:
- Standard I/O (Simple console-based communication)
- Named Pipes (Windows-specific high-performance IPC)
- Server-Sent Events (HTTP-based for web compatibility)
- Streamable HTTP
Base Transport Class (TTMSMCPTransport)
Class Hierarchy
Key Features
- Abstract base class defining the core transport interface
- Platform-specific (Windows-only) attribute
- Lifecycle management with start/stop controls
- Error handling infrastructure
- Message processing callback system
Usage Guidelines
Implementation Requirements
- Must inherit from
TTMSMCPTransport - Must implement all abstract methods
- Should maintain
FRunningstate accurately - Should call
LogErrorfor internal error reporting
Lifecycle Management
var
Transport: TTMSMCPTransport;
begin
Transport := TMyTransport.Create(nil);
try
Transport.OnProcessMessage := HandleMessage;
Transport.OnError := HandleError;
Transport.Run; // or Start + ProcessMessages loop
finally
Transport.Free;
end;
end;
Error Handling
procedure TMyTransport.LogError(const E: Exception);
begin
inherited; // Calls OnError if assigned
// Additional error handling
end;
Properties
| Property | Type | Description |
|---|---|---|
Running |
Boolean (read-only) |
Indicates whether the transport is currently active and processing messages |
OnProcessMessage |
TTMSMCPTransportProcessMessageEvent |
Callback for processing incoming messages |
OnError |
TProc<Exception> |
Error notification callback |
Methods
Core Methods
Initiates the transport service. Must be implemented by descendants. Terminates the transport service. Must be implemented by descendants. Runs the transport in blocking mode (does not return until stopped). Processes pending messages (for non-blocking implementations).Support Methods
Internal error logging method. Can be overridden for custom error handling. Helper method to check running status.Events
TTMSMCPTransportProcessMessageEvent
Message processing callback signature:
- Receives: Message body as string
- Returns: Response string
Named Pipes Transport
Architecture
- Server/Client model with asynchronous I/O
- Overlapped operations for high performance
- Thread-safe message queues
- Connection management
Key Components
TPipeServer
- Creates and manages named pipe instances
- Handles multiple client connections
- Broadcast capability
TPipeClient
- Connects to pipe servers
- Manages message sending/receiving
- Automatic reconnection logic
Advanced Features
- Write queue management with size limits
- Thread pool for connection handling
- Detailed error reporting with pipe contexts
- Memory-efficient buffering
Complete Example
// Server setup
procedure SetupPipeServer;
var
PipeServer: TPipeServer;
begin
PipeServer := TPipeServer.Create;
try
PipeServer.PipeName := 'MyAppService';
PipeServer.OnPipeMessage := HandlePipeMessage;
PipeServer.Active := True;
// Keep server running
while True do Sleep(1000);
finally
PipeServer.Free;
end;
end;
// Client implementation
procedure SendPipeMessage;
var
PipeClient: TPipeClient;
begin
PipeClient := TPipeClient.Create;
try
PipeClient.PipeName := 'MyAppService';
if PipeClient.Connect(2000) then
begin
PipeClient.Write(JSONMessage, Length(JSONMessage));
PipeClient.WaitUntilWriteQueueEmpty(5);
end;
finally
PipeClient.Free;
end;
end;
Streamable HTTP Transport
Architecture
- Abstract HTTP server layer with platform specific implementations
- HTTP-based protocol using text/event-stream
- CORS support for web applications
- SSL/TLS support for secure communications
- Connection keep-alive with ping mechanism
Key Features
- Client management with automatic cleanup
- Thread pool for concurrent connections
- Detailed logging infrastructure
URL reservation (Windows)
Starting from version TMS AI Studio v1.4, the server is http.sys-based on Windows systems. Http.sys needs a URL to be reserved. This reservation will automatically happen on first launch by triggering an elevated netsh command, and it reserves the url http://+:%PORT%/, where %PORT% equals to the Port property of the streamable HTTP transport. The URL will be registered for the Everyone usergroup. If you wish to register a custom URL or a different user group, proceed with manual commands before running the application. Keep in mind, the Port needs to be the same as the reserved URL.
You can do so by executing the following:
Read more about the netsh command here.
Certificates
Starting from version TMS AI Studio v1.4, the server is http.sys-based on Windows systems. This means a change in how the certificates are handled. For http.sys, a certificate hash, store name and app-id needs to be provided and registered. It's possible to do this 2 ways:
-
Provide the path to an INI file which contains the necessary information in the following format
Where
%HASH%is the hash of the certificate you with to bind to the server.%STORENAME%is the name of the certificate store which contains the certificate (e.g.My). This file needs to be assigend to the SSLCertFile property of the transport layer. -
Handle the registration manually via
netsh:
netsh http add sslcert ipport=0.0.0.0:%PORT% certhash=%HASH% certstorename=%STORENAME% appid={00112233-4455-6677-8899-AABBCCDDEEFF}
Read more about the netsh command here.
For the rest of the platforms, at this moment you need to use the certificate files as before.
Alternative to certificates
If the server is going to run on a Windows Server with IIS, it's possible to take advantage of IIS's reverse proxy support and let it handle the certificate. In that case, the server needs to run without UseSSL enabled.
Prerequisites
You'll need the URL Rewrite and the Application Request Routing modules.
In IIS manager:
- From the left-pane
Sitesthe site which should act as the intermediary - In the
IISsettings openURL rewrite - From the right-pane under
Actions, selectAdd Rule(s)... - Select
Reverse Proxy - Under the
Inbound rules, fill in the (localhost) URL where your server is running - Open the new inbound rule that was added
- Set the following:
- Requested URL > Matches the Pattern
- Using > Regular expressions (or Exact match, depending on your use case)
- Pattern: The pattern after the URL. For example, for SSE the pattern could be
sse|messagesin combination with Regular expressions. - Action type > Rewrite
- Rewrite URL > URL of your server +
{R:0}, for example:http://localhost:8934/{R:0}
Complete Example
procedure SetupSSETransport;
var
StreamableHTTPTransport: TTMSMCPStreamableHTTPTransport;
begin
StreamableHTTPTransport := TTMSMCPStreamableHTTPTransport.Create(nil);
try
// Basic configuration
StreamableHTTPTransport.Port := 8080;
// SSL configuration
StreamableHTTPTransport.ConfigureSSL(
'C:\myapp\certificate.ini'
);
// Message handling
StreamableHTTPTransport.OnProcessMessage :=
function(const body: string): string
var
Json: TJSONObject;
begin
Json := TJSONObject.ParseJSONValue(body) as TJSONObject;
try
Result := ProcessAPIRequest(Json);
finally
Json.Free;
end;
end;
// Start server
StreamableHTTPTransport.Start;
// Keep application running
while True do Sleep(1000);
finally
StreamableHTTPTransport.Free;
end;
end;
Standard I/O Transport
Architecture
- Simple stdin/stdout communication
- Blocking and non-blocking modes
- Minimal resource usage
- Platform independent
Key Features
- Line-based message processing
- Automatic output flushing
- Error resilience
- Simple integration
Complete Example
procedure RunStdIOTransport;
var
StdioTransport: TTMSMCPStdioTransport;
begin
StdioTransport := TTMSMCPStdioTransport.Create(nil);
try
StdioTransport.OnProcessMessage :=
function(const body: string): string
begin
try
Result := ExecuteCommand(body);
except
on E: Exception do
Result := 'ERROR: ' + E.Message;
end;
end;
// Run in blocking mode
StdioTransport.Run;
finally
StdioTransport.Free;
end;
end;
Comparison Matrix
| Feature | Named Pipes | SSE | STDIO |
|---|---|---|---|
| Platform Support | Windows only | Cross-platform | Cross-platform |
| Protocol | Named pipes IPC | HTTP/HTTPS | Standard streams |
| Performance | Very high | Medium | Low |
| Encryption | None | TLS/SSL | None |
| Connection Model | Persistent | Persistent | N/A |
| Max Message Size | 100MB | Configurable | Line buffer |
| Thread Safety | Fully thread-safe | Thread pool | Single-threaded |
| Best For | Windows IPC | Web applications | CLI tools |
| Complexity | High | Medium | Low |
Best Practices
General Guidelines
- Resource Management
- Always call
Stopbefore destruction - Free components in reverse creation order
-
Use try-finally blocks for cleanup
-
Error Handling
- Implement
OnErrorhandler for all transports - Validate incoming message size and format
-
Use timeouts for connection operations
-
Performance
- For high throughput: Use named pipes (Windows) or optimized SSE
- Limit message sizes to reasonable values
- Use connection pooling where available
Transport-Specific Recommendations
Named Pipes
- Set appropriate
MAX_BUFFERsize for expected messages - Use
WaitUntilWriteQueuesEmptyfor graceful shutdown - Implement proper error recovery for pipe disconnects
SSE / Streamable HTTP
- Always use HTTPS in production
- Implement client-side reconnection logic
- Monitor connection counts to prevent resource exhaustion
STDIO
- Add clear message delimiters (like newlines)
- Implement timeout handling for blocking operations
- Consider message size limitations
Advanced Topics
Custom Transport Implementation
To create a custom transport:
type
TMyCustomTransport = class(TTMSMCPTransport)
private
FInternalComponent: TMyCommunicationLib;
protected
procedure Start; override;
procedure Stop; override;
procedure Run; override;
procedure ProcessMessages; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
implementation
constructor TMyCustomTransport.Create(AOwner: TComponent);
begin
inherited;
FInternalComponent := TMyCommunicationLib.Create;
end;
destructor TMyCustomTransport.Destroy;
begin
Stop;
FInternalComponent.Free;
inherited;
end;
procedure TMyCustomTransport.Start;
begin
FInternalComponent.StartListener;
FRunning := True;
end;
// Implement other required methods...
Performance Optimization
- Named Pipes
- Adjust thread pool size based on expected load
- Use
LimitWriteQueuesto prevent memory issues -
Consider pipe buffer sizes
-
SSE
- Implement message compression
- Use HTTP/2 for better multiplexing
- Optimize JSON message formats
Security Considerations
- Named Pipes
- Implement proper ACLs for pipes
-
Validate client credentials
-
SSE
- Always use TLS 1.2+
- Implement authentication
-
Validate Origin headers
-
STDIO
- Sanitize all input
- Implement rate limiting
Troubleshooting
Common Issues
Connection Problems
- Named Pipes:
- Error 231 (Pipe busy): Increase pipe instances or add retry logic
-
Error 233 (No process): Remote end disconnected
-
SSE:
- CORS issues: Verify
Access-Control-*headers - SSL errors: Check certificate chain and dates
Performance Issues
- High latency:
- Check network conditions (SSE)
-
Verify buffer sizes (Pipes)
-
Throughput limits:
- Adjust thread pool sizes
- Optimize message processing
Memory Problems
- Growing queues:
- Implement queue limits
- Monitor with
GetCountmethods
Debugging Tips
-
Enable Logging
-
Diagnostic Tools
- Use Wireshark for SSE traffic
- Windows Pipe Monitor for named pipes
-
Process Explorer for handle checks
-
Error Recovery