mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-02-08 06:13:07 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a57b400bd0 |
12
CHANGELOG.md
12
CHANGELOG.md
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [2.34.4] - 2026-02-07
|
||||
|
||||
### Fixed
|
||||
|
||||
- **MCP Apps: Fix blank UI rendering in Claude**: Rewrote `useToolData` hook to use the official `useApp` hook from `@modelcontextprotocol/ext-apps/react` instead of manually managing `App` lifecycle
|
||||
- Proper initialization handshake with host via `appInfo` and `capabilities`
|
||||
- Handlers registered via `onAppCreated` callback (before `connect()`) to avoid race conditions
|
||||
- Removed `app.close()` on unmount which caused issues with React Strict Mode
|
||||
- Added visible error and connection states with inline colors for debugging
|
||||
|
||||
Conceived by Romuald Czlonkowski - https://www.aiadvisors.pl/en
|
||||
|
||||
## [2.34.3] - 2026-02-07
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "n8n-mcp",
|
||||
"version": "2.34.3",
|
||||
"version": "2.34.4",
|
||||
"description": "Integration between n8n workflow automation and Model Context Protocol (MCP)",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@@ -5,10 +5,18 @@ import { useToolData } from '@shared/hooks/useToolData';
|
||||
import type { OperationResultData } from '@shared/types';
|
||||
|
||||
export default function App() {
|
||||
const data = useToolData<OperationResultData>();
|
||||
const { data, error, isConnected } = useToolData<OperationResultData>();
|
||||
|
||||
if (error) {
|
||||
return <div style={{ padding: '16px', color: '#ef4444' }}>Error: {error}</div>;
|
||||
}
|
||||
|
||||
if (!isConnected) {
|
||||
return <div style={{ padding: '16px', color: '#9ca3af' }}>Connecting...</div>;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return <div style={{ padding: '16px', color: 'var(--n8n-text-muted)' }}>Loading...</div>;
|
||||
return <div style={{ padding: '16px', color: '#9ca3af' }}>Waiting for data...</div>;
|
||||
}
|
||||
|
||||
const isSuccess = data.status === 'success';
|
||||
|
||||
@@ -5,10 +5,18 @@ import { useToolData } from '@shared/hooks/useToolData';
|
||||
import type { ValidationSummaryData } from '@shared/types';
|
||||
|
||||
export default function App() {
|
||||
const data = useToolData<ValidationSummaryData>();
|
||||
const { data, error, isConnected } = useToolData<ValidationSummaryData>();
|
||||
|
||||
if (error) {
|
||||
return <div style={{ padding: '16px', color: '#ef4444' }}>Error: {error}</div>;
|
||||
}
|
||||
|
||||
if (!isConnected) {
|
||||
return <div style={{ padding: '16px', color: '#9ca3af' }}>Connecting...</div>;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return <div style={{ padding: '16px', color: 'var(--n8n-text-muted)' }}>Loading...</div>;
|
||||
return <div style={{ padding: '16px', color: '#9ca3af' }}>Waiting for data...</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { App } from '@modelcontextprotocol/ext-apps';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { useApp } from '@modelcontextprotocol/ext-apps/react';
|
||||
|
||||
export function useToolData<T>(): T | null {
|
||||
interface UseToolDataResult<T> {
|
||||
data: T | null;
|
||||
error: string | null;
|
||||
isConnected: boolean;
|
||||
}
|
||||
|
||||
export function useToolData<T>(): UseToolDataResult<T> {
|
||||
const [data, setData] = useState<T | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const app = new App();
|
||||
|
||||
const onAppCreated = useCallback((app: any) => {
|
||||
app.ontoolresult = (result: any) => {
|
||||
// The host pushes tool result content; parse the first text item as JSON
|
||||
if (result?.content) {
|
||||
const textItem = Array.isArray(result.content)
|
||||
? result.content.find((c: any) => c.type === 'text')
|
||||
@@ -17,19 +20,22 @@ export function useToolData<T>(): T | null {
|
||||
try {
|
||||
setData(JSON.parse(textItem.text) as T);
|
||||
} catch {
|
||||
// Not JSON — use raw text as-is
|
||||
setData(textItem.text as unknown as T);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
app.connect();
|
||||
|
||||
return () => {
|
||||
app.close();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return data;
|
||||
const { isConnected, error } = useApp({
|
||||
appInfo: { name: 'n8n-mcp-ui', version: '1.0.0' },
|
||||
capabilities: {},
|
||||
onAppCreated,
|
||||
});
|
||||
|
||||
return {
|
||||
data,
|
||||
error: error?.message ?? null,
|
||||
isConnected,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user