mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-03-31 22:53:07 +00:00
fix: resolve double URL-encoding in datatable filter/sortBy query params (#652)
This commit is contained in:
committed by
GitHub
parent
c5665632af
commit
6f6668acc4
@@ -2861,11 +2861,10 @@ export async function handleGetRows(args: unknown, context?: InstanceContext): P
|
||||
const { tableId, filter, sortBy, ...params } = getRowsSchema.parse(args);
|
||||
const queryParams: Record<string, unknown> = { ...params };
|
||||
if (filter) {
|
||||
const filterStr = typeof filter === 'string' ? filter : JSON.stringify(filter);
|
||||
queryParams.filter = encodeURIComponent(filterStr);
|
||||
queryParams.filter = typeof filter === 'string' ? filter : JSON.stringify(filter);
|
||||
}
|
||||
if (sortBy) {
|
||||
queryParams.sortBy = encodeURIComponent(sortBy);
|
||||
queryParams.sortBy = sortBy;
|
||||
}
|
||||
const result = await client.getDataTableRows(tableId, queryParams as any);
|
||||
return {
|
||||
@@ -2931,7 +2930,7 @@ export async function handleDeleteRows(args: unknown, context?: InstanceContext)
|
||||
const client = ensureApiConfigured(context);
|
||||
const { tableId, filter, ...params } = deleteRowsSchema.parse(args);
|
||||
const queryParams = {
|
||||
filter: encodeURIComponent(JSON.stringify(filter)),
|
||||
filter: JSON.stringify(filter),
|
||||
...params,
|
||||
};
|
||||
const result = await client.deleteDataTableRows(tableId, queryParams as any);
|
||||
|
||||
@@ -9,7 +9,7 @@ export const n8nManageDatatableDoc: ToolDocumentation = {
|
||||
example: 'n8n_manage_datatable({action: "createTable", name: "Contacts", columns: [{name: "email", type: "string"}]})',
|
||||
performance: 'Fast (100-500ms)',
|
||||
tips: [
|
||||
'Table actions: createTable, listTables, getTable, updateTable, deleteTable',
|
||||
'Table actions: createTable, listTables, getTable, updateTable (rename only), deleteTable',
|
||||
'Row actions: getRows, insertRows, updateRows, upsertRows, deleteRows',
|
||||
'Use dryRun: true to preview update/upsert/delete before applying',
|
||||
'Filter supports: eq, neq, like, ilike, gt, gte, lt, lte conditions',
|
||||
@@ -22,7 +22,7 @@ export const n8nManageDatatableDoc: ToolDocumentation = {
|
||||
- **createTable**: Create a new data table with optional typed columns
|
||||
- **listTables**: List all data tables (paginated)
|
||||
- **getTable**: Get table details and column definitions by ID
|
||||
- **updateTable**: Rename an existing table
|
||||
- **updateTable**: Rename an existing table (name only — column modifications not supported via API)
|
||||
- **deleteTable**: Permanently delete a table and all its rows
|
||||
|
||||
**Row Actions:**
|
||||
|
||||
@@ -637,7 +637,10 @@ export class N8nApiClient {
|
||||
|
||||
async getDataTableRows(id: string, params: DataTableRowListParams = {}): Promise<{ data: DataTableRow[]; nextCursor?: string | null }> {
|
||||
try {
|
||||
const response = await this.client.get(`/data-tables/${id}/rows`, { params });
|
||||
const response = await this.client.get(`/data-tables/${id}/rows`, {
|
||||
params,
|
||||
paramsSerializer: (p) => this.serializeDataTableParams(p),
|
||||
});
|
||||
return this.validateListResponse<DataTableRow>(response.data, 'data-table-rows');
|
||||
} catch (error) {
|
||||
throw handleN8nApiError(error);
|
||||
@@ -673,13 +676,29 @@ export class N8nApiClient {
|
||||
|
||||
async deleteDataTableRows(id: string, params: DataTableDeleteRowsParams): Promise<any> {
|
||||
try {
|
||||
const response = await this.client.delete(`/data-tables/${id}/rows/delete`, { params });
|
||||
const response = await this.client.delete(`/data-tables/${id}/rows/delete`, {
|
||||
params,
|
||||
paramsSerializer: (p) => this.serializeDataTableParams(p),
|
||||
});
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
throw handleN8nApiError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes data table query params with explicit encodeURIComponent.
|
||||
* Axios's default serializer doesn't encode some reserved chars that n8n rejects.
|
||||
*/
|
||||
private serializeDataTableParams(params: Record<string, any>): string {
|
||||
const parts: string[] = [];
|
||||
for (const [key, value] of Object.entries(params)) {
|
||||
if (value === undefined || value === null) continue;
|
||||
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
||||
}
|
||||
return parts.join('&');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and normalizes n8n API list responses.
|
||||
* Handles both modern format {data: [], nextCursor?: string} and legacy array format.
|
||||
|
||||
Reference in New Issue
Block a user